summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClement Ho <ClemMakesApps@gmail.com>2017-06-09 15:51:11 -0500
committerClement Ho <ClemMakesApps@gmail.com>2017-06-09 15:51:11 -0500
commitfd760b78bc0ef7a75be9193fb66a8b37a6a9b857 (patch)
tree2049730ec94e24b00616c7d699c15e0c57038bdb
parentf08a8ae18f74ad086695d62ff78ada2796e65829 (diff)
parentb1bf6d88fceb24663bfe4be2d9cc111710d9126b (diff)
downloadgitlab-ce-fd760b78bc0ef7a75be9193fb66a8b37a6a9b857.tar.gz
Merge commit 'b1bf6d88fceb24663bfe4be2d9cc111710d9126b' into 9-3-stable
-rw-r--r--app/assets/javascripts/build.js4
-rw-r--r--app/assets/javascripts/dispatcher.js5
-rw-r--r--app/assets/javascripts/filterable_list.js82
-rw-r--r--app/assets/javascripts/groups/components/group_folder.vue27
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue220
-rw-r--r--app/assets/javascripts/groups/components/groups.vue39
-rw-r--r--app/assets/javascripts/groups/event_hub.js3
-rw-r--r--app/assets/javascripts/groups/groups_filterable_list.js87
-rw-r--r--app/assets/javascripts/groups/index.js190
-rw-r--r--app/assets/javascripts/groups/services/groups_service.js38
-rw-r--r--app/assets/javascripts/groups/stores/groups_store.js151
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js4
-rw-r--r--app/assets/javascripts/locale/bg/app.js1
-rw-r--r--app/assets/javascripts/locale/de/app.js2
-rw-r--r--app/assets/javascripts/locale/en/app.js2
-rw-r--r--app/assets/javascripts/locale/es/app.js2
-rw-r--r--app/assets/javascripts/locale/pt_BR/app.js1
-rw-r--r--app/assets/javascripts/locale/zh_CN/app.js2
-rw-r--r--app/assets/javascripts/locale/zh_HK/app.js2
-rw-r--r--app/assets/javascripts/locale/zh_TW/app.js2
-rw-r--r--app/assets/javascripts/pipelines/pipelines.js2
-rw-r--r--app/assets/stylesheets/framework/awards.scss8
-rw-r--r--app/assets/stylesheets/framework/lists.scss100
-rw-r--r--app/assets/stylesheets/pages/issuable.scss3
-rw-r--r--app/assets/stylesheets/pages/issues.scss19
-rw-r--r--app/assets/stylesheets/pages/members.scss35
-rw-r--r--app/controllers/concerns/membership_actions.rb9
-rw-r--r--app/controllers/dashboard/groups_controller.rb28
-rw-r--r--app/controllers/projects/blob_controller.rb14
-rw-r--r--app/controllers/projects/labels_controller.rb6
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb4
-rw-r--r--app/helpers/groups_helper.rb2
-rw-r--r--app/helpers/nav_helper.rb2
-rw-r--r--app/models/blob.rb10
-rw-r--r--app/models/blob_viewer/base.rb2
-rw-r--r--app/models/blob_viewer/empty.rb1
-rw-r--r--app/models/blob_viewer/server_side.rb4
-rw-r--r--app/models/commit.rb27
-rw-r--r--app/models/project.rb37
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/serializers/group_entity.rb46
-rw-r--r--app/serializers/group_serializer.rb19
-rw-r--r--app/services/ci/create_pipeline_service.rb6
-rw-r--r--app/uploaders/gitlab_uploader.rb6
-rw-r--r--app/views/dashboard/groups/_groups.html.haml13
-rw-r--r--app/views/dashboard/groups/index.html.haml5
-rw-r--r--app/views/projects/diffs/_content.html.haml2
-rw-r--r--app/views/projects/diffs/viewers/_text.html.haml2
-rw-r--r--app/views/projects/group_links/_index.html.haml53
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml20
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml12
-rw-r--r--app/views/projects/pipeline_schedules/_table.html.haml10
-rw-r--r--app/views/projects/pipeline_schedules/_tabs.html.haml6
-rw-r--r--app/views/projects/pipeline_schedules/edit.html.haml4
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml4
-rw-r--r--app/views/projects/pipeline_schedules/new.html.haml4
-rw-r--r--app/views/projects/project_members/_index.html.haml20
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml37
-rw-r--r--app/views/projects/project_members/_new_shared_group.html.haml20
-rw-r--r--app/views/projects/settings/members/show.html.haml3
-rw-r--r--app/views/shared/_label.html.haml2
-rw-r--r--app/views/shared/groups/_dropdown.html.haml12
-rw-r--r--changelogs/unreleased/12614-fix-long-message.yml4
-rw-r--r--changelogs/unreleased/25426-group-dashboard-ui.yml4
-rw-r--r--changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml4
-rw-r--r--changelogs/unreleased/32720-emoji-spacing.yml4
-rw-r--r--changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml4
-rw-r--r--changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml4
-rw-r--r--changelogs/unreleased/allow-reporters-to-promote-group-labels.yml4
-rw-r--r--changelogs/unreleased/artifacts-keyboard-shortcuts.yml4
-rw-r--r--changelogs/unreleased/ce-31853-projects-shared-groups.yml4
-rw-r--r--changelogs/unreleased/zj-i18n-pipeline-schedules.yml4
-rw-r--r--changelogs/unreleased/zj-prom-pipeline-count.yml4
-rw-r--r--config/webpack.config.js2
-rw-r--r--db/schema.rb3
-rw-r--r--doc/api/README.md9
-rw-r--r--doc/api/projects.md2
-rw-r--r--doc/ci/runners/README.md214
-rw-r--r--doc/ci/runners/img/shared_runners_admin.pngbin0 -> 29192 bytes
-rw-r--r--doc/ci/runners/project_specific.pngbin30196 -> 0 bytes
-rw-r--r--doc/ci/runners/shared_runner.pngbin17797 -> 0 bytes
-rw-r--r--doc/ci/triggers/README.md160
-rw-r--r--doc/ci/triggers/img/triggers_page.pngbin110560 -> 20857 bytes
-rw-r--r--doc/ci/variables/README.md1
-rw-r--r--doc/install/requirements.md3
-rw-r--r--doc/user/project/img/protected_branches_delete.pngbin0 -> 21510 bytes
-rw-r--r--doc/user/project/protected_branches.md27
-rw-r--r--features/steps/project/project_group_links.rb7
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/files.rb2
-rw-r--r--lib/api/v3/files.rb2
-rw-r--r--lib/gitlab/blame.rb2
-rw-r--r--lib/gitlab/diff/file.rb50
-rw-r--r--lib/gitlab/diff/file_collection/merge_request_diff.rb5
-rw-r--r--lib/gitlab/diff/highlight.rb17
-rw-r--r--lib/gitlab/git/repository.rb5
-rw-r--r--lib/gitlab/highlight.rb8
-rw-r--r--lib/gitlab/i18n.rb4
-rw-r--r--lib/gitlab/path_regex.rb1
-rw-r--r--locale/bg/gitlab.po260
-rw-r--r--locale/bg/gitlab.po.time_stamp0
-rw-r--r--locale/de/gitlab.pobin17365 -> 18834 bytes
-rw-r--r--locale/en/gitlab.po99
-rw-r--r--locale/es/gitlab.pobin22957 -> 19238 bytes
-rw-r--r--locale/gitlab.pot97
-rw-r--r--locale/pt_BR/gitlab.po260
-rw-r--r--locale/pt_BR/gitlab.po.time_stamp0
-rw-r--r--locale/zh_CN/gitlab.po769
-rw-r--r--locale/zh_HK/gitlab.po769
-rw-r--r--locale/zh_TW/gitlab.po769
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb7
-rw-r--r--spec/controllers/projects/labels_controller_spec.rb6
-rw-r--r--spec/features/dashboard/groups_list_spec.rb122
-rw-r--r--spec/features/projects/group_links_spec.rb9
-rw-r--r--spec/helpers/application_helper_spec.rb8
-rw-r--r--spec/javascripts/groups/group_item_spec.js102
-rw-r--r--spec/javascripts/groups/groups_spec.js64
-rw-r--r--spec/javascripts/groups/mock_data.js110
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js8
-rw-r--r--spec/javascripts/test_bundle.js1
-rw-r--r--spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb12
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb28
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb41
-rw-r--r--spec/lib/gitlab/highlight_spec.rb37
-rw-r--r--spec/migrations/rename_system_namespaces_spec.rb12
-rw-r--r--spec/models/blob_spec.rb8
-rw-r--r--spec/models/commit_spec.rb26
-rw-r--r--spec/models/group_spec.rb2
-rw-r--r--spec/models/project_spec.rb2
-rw-r--r--spec/models/user_spec.rb2
-rw-r--r--spec/policies/project_snippet_policy_spec.rb4
-rw-r--r--spec/requests/git_http_spec.rb2
-rw-r--r--spec/requests/openid_connect_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb8
-rw-r--r--spec/services/merge_requests/merge_request_diff_cache_service_spec.rb4
-rw-r--r--spec/services/projects/participants_service_spec.rb4
-rw-r--r--spec/unicorn/unicorn_spec.rb4
137 files changed, 5025 insertions, 687 deletions
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index 072a899e9f2..3b2bb6f082f 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -80,7 +80,7 @@ window.Build = (function () {
this.$scrollContainer.niceScroll({
cursorcolor: '#fff',
cursoropacitymin: 1,
- cursorwidth: '3px',
+ cursorwidth: '7px',
railpadding: { top: 5, bottom: 5, right: 5 },
});
@@ -238,7 +238,7 @@ window.Build = (function () {
};
Build.prototype.toggleSidebar = function (shouldHide) {
- const shouldShow = !shouldHide;
+ const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
this.$buildTrace
.toggleClass('sidebar-expanded', shouldShow)
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 0c420c12345..51cc8c085b2 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -160,9 +160,6 @@ import initSettingsPanels from './settings_panels';
case 'admin:projects:index':
new ProjectsList();
break;
- case 'dashboard:groups:index':
- new GroupsList();
- break;
case 'explore:groups:index':
new GroupsList();
@@ -374,9 +371,11 @@ import initSettingsPanels from './settings_panels';
new ProjectFork();
break;
case 'projects:artifacts:browse':
+ new ShortcutsNavigation();
new BuildArtifacts();
break;
case 'projects:artifacts:file':
+ new ShortcutsNavigation();
new BlobViewer();
break;
case 'help:index':
diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js
index aaaeb9bddb1..139206cc185 100644
--- a/app/assets/javascripts/filterable_list.js
+++ b/app/assets/javascripts/filterable_list.js
@@ -8,39 +8,87 @@ export default class FilterableList {
this.filterForm = form;
this.listFilterElement = filter;
this.listHolderElement = holder;
+ this.isBusy = false;
+ }
+
+ getFilterEndpoint() {
+ return `${this.filterForm.getAttribute('action')}?${$(this.filterForm).serialize()}`;
+ }
+
+ getPagePath() {
+ return this.getFilterEndpoint();
}
initSearch() {
- this.debounceFilter = _.debounce(this.filterResults.bind(this), 500);
+ // Wrap to prevent passing event arguments to .filterResults;
+ this.debounceFilter = _.debounce(this.onFilterInput.bind(this), 500);
- this.listFilterElement.removeEventListener('input', this.debounceFilter);
+ this.unbindEvents();
+ this.bindEvents();
+ }
+
+ onFilterInput() {
+ const $form = $(this.filterForm);
+ const queryData = {};
+ const filterGroupsParam = $form.find('[name="filter_groups"]').val();
+
+ if (filterGroupsParam) {
+ queryData.filter_groups = filterGroupsParam;
+ }
+
+ this.filterResults(queryData);
+
+ if (this.setDefaultFilterOption) {
+ this.setDefaultFilterOption();
+ }
+ }
+
+ bindEvents() {
this.listFilterElement.addEventListener('input', this.debounceFilter);
}
- filterResults() {
- const form = this.filterForm;
- const filterUrl = `${form.getAttribute('action')}?${$(form).serialize()}`;
+ unbindEvents() {
+ this.listFilterElement.removeEventListener('input', this.debounceFilter);
+ }
+
+ filterResults(queryData) {
+ if (this.isBusy) {
+ return false;
+ }
$(this.listHolderElement).fadeTo(250, 0.5);
return $.ajax({
- url: form.getAttribute('action'),
- data: $(form).serialize(),
+ url: this.getFilterEndpoint(),
+ data: queryData,
type: 'GET',
dataType: 'json',
context: this,
- complete() {
- $(this.listHolderElement).fadeTo(250, 1);
+ complete: this.onFilterComplete,
+ beforeSend: () => {
+ this.isBusy = true;
},
- success(data) {
- this.listHolderElement.innerHTML = data.html;
-
- // Change url so if user reload a page - search results are saved
- return window.history.replaceState({
- page: filterUrl,
-
- }, document.title, filterUrl);
+ success: (response, textStatus, xhr) => {
+ this.onFilterSuccess(response, xhr, queryData);
},
});
}
+
+ onFilterSuccess(response, xhr, queryData) {
+ if (response.html) {
+ this.listHolderElement.innerHTML = response.html;
+ }
+
+ // Change url so if user reload a page - search results are saved
+ const currentPath = this.getPagePath(queryData);
+
+ return window.history.replaceState({
+ page: currentPath,
+ }, document.title, currentPath);
+ }
+
+ onFilterComplete() {
+ this.isBusy = false;
+ $(this.listHolderElement).fadeTo(250, 1);
+ }
}
diff --git a/app/assets/javascripts/groups/components/group_folder.vue b/app/assets/javascripts/groups/components/group_folder.vue
new file mode 100644
index 00000000000..7cc6c4b0359
--- /dev/null
+++ b/app/assets/javascripts/groups/components/group_folder.vue
@@ -0,0 +1,27 @@
+<script>
+export default {
+ props: {
+ groups: {
+ type: Object,
+ required: true,
+ },
+ baseGroup: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+};
+</script>
+
+<template>
+ <ul class="content-list group-list-tree">
+ <group-item
+ v-for="(group, index) in groups"
+ :key="index"
+ :group="group"
+ :base-group="baseGroup"
+ :collection="groups"
+ />
+ </ul>
+</template>
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
new file mode 100644
index 00000000000..32815b9f73e
--- /dev/null
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -0,0 +1,220 @@
+<script>
+import eventHub from '../event_hub';
+
+export default {
+ props: {
+ group: {
+ type: Object,
+ required: true,
+ },
+ baseGroup: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ collection: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+ methods: {
+ onClickRowGroup(e) {
+ e.stopPropagation();
+
+ // Skip for buttons
+ if (!(e.target.tagName === 'A') && !(e.target.tagName === 'I' && e.target.parentElement.tagName === 'A')) {
+ if (this.group.hasSubgroups) {
+ eventHub.$emit('toggleSubGroups', this.group);
+ } else {
+ window.location.href = this.group.webUrl;
+ }
+ }
+ },
+ onLeaveGroup(e) {
+ e.preventDefault();
+
+ // eslint-disable-next-line no-alert
+ if (confirm(`Are you sure you want to leave the "${this.group.fullName}" group?`)) {
+ this.leaveGroup();
+ }
+ },
+ leaveGroup() {
+ eventHub.$emit('leaveGroup', this.group, this.collection);
+ },
+ },
+ computed: {
+ groupDomId() {
+ return `group-${this.group.id}`;
+ },
+ rowClass() {
+ return {
+ 'group-row': true,
+ 'is-open': this.group.isOpen,
+ 'has-subgroups': this.group.hasSubgroups,
+ 'no-description': !this.group.description,
+ };
+ },
+ visibilityIcon() {
+ return {
+ fa: true,
+ 'fa-globe': this.group.visibility === 'public',
+ 'fa-shield': this.group.visibility === 'internal',
+ 'fa-lock': this.group.visibility === 'private',
+ };
+ },
+ fullPath() {
+ let fullPath = '';
+
+ if (this.group.isOrphan) {
+ // check if current group is baseGroup
+ if (Object.keys(this.baseGroup).length > 0 && this.baseGroup !== this.group) {
+ // Remove baseGroup prefix from our current group.fullName. e.g:
+ // baseGroup.fullName: `level1`
+ // group.fullName: `level1 / level2 / level3`
+ // Result: `level2 / level3`
+ const gfn = this.group.fullName;
+ const bfn = this.baseGroup.fullName;
+ const length = bfn.length;
+ const start = gfn.indexOf(bfn);
+ const extraPrefixChars = 3;
+
+ fullPath = gfn.substr(start + length + extraPrefixChars);
+ } else {
+ fullPath = this.group.fullName;
+ }
+ } else {
+ fullPath = this.group.name;
+ }
+
+ return fullPath;
+ },
+ hasGroups() {
+ return Object.keys(this.group.subGroups).length > 0;
+ },
+ },
+};
+</script>
+
+<template>
+ <li
+ @click.stop="onClickRowGroup"
+ :id="groupDomId"
+ :class="rowClass"
+ >
+ <div
+ class="group-row-contents">
+ <div
+ class="controls">
+ <a
+ v-if="group.canEdit"
+ class="edit-group btn"
+ :href="group.editPath">
+ <i
+ class="fa fa-cogs"
+ aria-hidden="true"
+ >
+ </i>
+ </a>
+ <a
+ @click="onLeaveGroup"
+ :href="group.leavePath"
+ class="leave-group btn"
+ title="Leave this group">
+ <i
+ class="fa fa-sign-out"
+ aria-hidden="true"
+ >
+ </i>
+ </a>
+ </div>
+ <div
+ class="stats">
+ <span
+ class="number-projects">
+ <i
+ class="fa fa-bookmark"
+ aria-hidden="true"
+ >
+ </i>
+ {{group.numberProjects}}
+ </span>
+ <span
+ class="number-users">
+ <i
+ class="fa fa-users"
+ aria-hidden="true"
+ >
+ </i>
+ {{group.numberUsers}}
+ </span>
+ <span
+ class="group-visibility">
+ <i
+ :class="visibilityIcon"
+ aria-hidden="true"
+ >
+ </i>
+ </span>
+ </div>
+ <div
+ class="folder-toggle-wrap">
+ <span
+ class="folder-caret"
+ v-if="group.hasSubgroups">
+ <i
+ v-if="group.isOpen"
+ class="fa fa-caret-down"
+ aria-hidden="true"
+ >
+ </i>
+ <i
+ v-if="!group.isOpen"
+ class="fa fa-caret-right"
+ aria-hidden="true"
+ >
+ </i>
+ </span>
+ <span class="folder-icon">
+ <i
+ v-if="group.isOpen"
+ class="fa fa-folder-open"
+ aria-hidden="true"
+ >
+ </i>
+ <i
+ v-if="!group.isOpen"
+ class="fa fa-folder"
+ aria-hidden="true">
+ </i>
+ </span>
+ </div>
+ <div
+ class="avatar-container s40 hidden-xs">
+ <a
+ :href="group.webUrl">
+ <img
+ class="avatar s40"
+ :src="group.avatarUrl"
+ />
+ </a>
+ </div>
+ <div
+ class="title">
+ <a
+ :href="group.webUrl">{{fullPath}}</a>
+ <template v-if="group.permissions.humanGroupAccess">
+ as
+ <span class="access-type">{{group.permissions.humanGroupAccess}}</span>
+ </template>
+ </div>
+ <div
+ class="description">{{group.description}}</div>
+ </div>
+ <group-folder
+ v-if="group.isOpen && hasGroups"
+ :groups="group.subGroups"
+ :baseGroup="group"
+ />
+ </li>
+</template>
diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue
new file mode 100644
index 00000000000..36a04d4202f
--- /dev/null
+++ b/app/assets/javascripts/groups/components/groups.vue
@@ -0,0 +1,39 @@
+<script>
+import tablePagination from '~/vue_shared/components/table_pagination.vue';
+import eventHub from '../event_hub';
+
+export default {
+ props: {
+ groups: {
+ type: Object,
+ required: true,
+ },
+ pageInfo: {
+ type: Object,
+ required: true,
+ },
+ },
+ components: {
+ tablePagination,
+ },
+ methods: {
+ change(page) {
+ const filterGroupsParam = gl.utils.getParameterByName('filter_groups');
+ const sortParam = gl.utils.getParameterByName('sort');
+ eventHub.$emit('fetchPage', page, filterGroupsParam, sortParam);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="groups-list-tree-container">
+ <group-folder
+ :groups="groups"
+ />
+ <table-pagination
+ :change="change"
+ :pageInfo="pageInfo"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/groups/event_hub.js b/app/assets/javascripts/groups/event_hub.js
new file mode 100644
index 00000000000..0948c2e5352
--- /dev/null
+++ b/app/assets/javascripts/groups/event_hub.js
@@ -0,0 +1,3 @@
+import Vue from 'vue';
+
+export default new Vue();
diff --git a/app/assets/javascripts/groups/groups_filterable_list.js b/app/assets/javascripts/groups/groups_filterable_list.js
new file mode 100644
index 00000000000..439a931ddad
--- /dev/null
+++ b/app/assets/javascripts/groups/groups_filterable_list.js
@@ -0,0 +1,87 @@
+import FilterableList from '~/filterable_list';
+import eventHub from './event_hub';
+
+export default class GroupFilterableList extends FilterableList {
+ constructor({ form, filter, holder, filterEndpoint, pagePath }) {
+ super(form, filter, holder);
+ this.form = form;
+ this.filterEndpoint = filterEndpoint;
+ this.pagePath = pagePath;
+ this.$dropdown = $('.js-group-filter-dropdown-wrap');
+ }
+
+ getFilterEndpoint() {
+ return this.filterEndpoint;
+ }
+
+ getPagePath(queryData) {
+ const params = queryData ? $.param(queryData) : '';
+ const queryString = params ? `?${params}` : '';
+ return `${this.pagePath}${queryString}`;
+ }
+
+ bindEvents() {
+ super.bindEvents();
+
+ this.onFormSubmitWrapper = this.onFormSubmit.bind(this);
+ this.onFilterOptionClikWrapper = this.onOptionClick.bind(this);
+
+ this.filterForm.addEventListener('submit', this.onFormSubmitWrapper);
+ this.$dropdown.on('click', 'a', this.onFilterOptionClikWrapper);
+ }
+
+ onFormSubmit(e) {
+ e.preventDefault();
+
+ const $form = $(this.form);
+ const filterGroupsParam = $form.find('[name="filter_groups"]').val();
+ const queryData = {};
+
+ if (filterGroupsParam) {
+ queryData.filter_groups = filterGroupsParam;
+ }
+
+ this.filterResults(queryData);
+ this.setDefaultFilterOption();
+ }
+
+ setDefaultFilterOption() {
+ const defaultOption = $.trim(this.$dropdown.find('.dropdown-menu a:first-child').text());
+ this.$dropdown.find('.dropdown-label').text(defaultOption);
+ }
+
+ onOptionClick(e) {
+ e.preventDefault();
+
+ const queryData = {};
+ const sortParam = gl.utils.getParameterByName('sort', e.currentTarget.href);
+
+ if (sortParam) {
+ queryData.sort = sortParam;
+ }
+
+ this.filterResults(queryData);
+
+ // Active selected option
+ this.$dropdown.find('.dropdown-label').text($.trim(e.currentTarget.text));
+
+ // Clear current value on search form
+ this.form.querySelector('[name="filter_groups"]').value = '';
+ }
+
+ onFilterSuccess(data, xhr, queryData) {
+ super.onFilterSuccess(data, xhr, queryData);
+
+ const paginationData = {
+ 'X-Per-Page': xhr.getResponseHeader('X-Per-Page'),
+ 'X-Page': xhr.getResponseHeader('X-Page'),
+ 'X-Total': xhr.getResponseHeader('X-Total'),
+ 'X-Total-Pages': xhr.getResponseHeader('X-Total-Pages'),
+ 'X-Next-Page': xhr.getResponseHeader('X-Next-Page'),
+ 'X-Prev-Page': xhr.getResponseHeader('X-Prev-Page'),
+ };
+
+ eventHub.$emit('updateGroups', data);
+ eventHub.$emit('updatePagination', paginationData);
+ }
+}
diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js
new file mode 100644
index 00000000000..ff601db2aa6
--- /dev/null
+++ b/app/assets/javascripts/groups/index.js
@@ -0,0 +1,190 @@
+/* global Flash */
+
+import Vue from 'vue';
+import GroupFilterableList from './groups_filterable_list';
+import GroupsComponent from './components/groups.vue';
+import GroupFolder from './components/group_folder.vue';
+import GroupItem from './components/group_item.vue';
+import GroupsStore from './stores/groups_store';
+import GroupsService from './services/groups_service';
+import eventHub from './event_hub';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const el = document.getElementById('dashboard-group-app');
+
+ // Don't do anything if element doesn't exist (No groups)
+ // This is for when the user enters directly to the page via URL
+ if (!el) {
+ return;
+ }
+
+ Vue.component('groups-component', GroupsComponent);
+ Vue.component('group-folder', GroupFolder);
+ Vue.component('group-item', GroupItem);
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ data() {
+ this.store = new GroupsStore();
+ this.service = new GroupsService(el.dataset.endpoint);
+
+ return {
+ store: this.store,
+ isLoading: true,
+ state: this.store.state,
+ loading: true,
+ };
+ },
+ computed: {
+ isEmpty() {
+ return Object.keys(this.state.groups).length === 0;
+ },
+ },
+ methods: {
+ fetchGroups(parentGroup) {
+ let parentId = null;
+ let getGroups = null;
+ let page = null;
+ let sort = null;
+ let pageParam = null;
+ let sortParam = null;
+ let filterGroups = null;
+ let filterGroupsParam = null;
+
+ if (parentGroup) {
+ parentId = parentGroup.id;
+ } else {
+ this.isLoading = true;
+ }
+
+ pageParam = gl.utils.getParameterByName('page');
+ if (pageParam) {
+ page = pageParam;
+ }
+
+ filterGroupsParam = gl.utils.getParameterByName('filter_groups');
+ if (filterGroupsParam) {
+ filterGroups = filterGroupsParam;
+ }
+
+ sortParam = gl.utils.getParameterByName('sort');
+ if (sortParam) {
+ sort = sortParam;
+ }
+
+ getGroups = this.service.getGroups(parentId, page, filterGroups, sort);
+ getGroups
+ .then(response => response.json())
+ .then((response) => {
+ this.isLoading = false;
+
+ this.updateGroups(response, parentGroup);
+ })
+ .catch(this.handleErrorResponse);
+
+ return getGroups;
+ },
+ fetchPage(page, filterGroups, sort) {
+ this.isLoading = true;
+
+ return this.service
+ .getGroups(null, page, filterGroups, sort)
+ .then((response) => {
+ this.isLoading = false;
+ $.scrollTo(0);
+
+ const currentPath = gl.utils.mergeUrlParams({ page }, window.location.href);
+ window.history.replaceState({
+ page: currentPath,
+ }, document.title, currentPath);
+
+ this.updateGroups(response.json());
+ this.updatePagination(response.headers);
+ })
+ .catch(this.handleErrorResponse);
+ },
+ toggleSubGroups(parentGroup = null) {
+ if (!parentGroup.isOpen) {
+ this.store.resetGroups(parentGroup);
+ this.fetchGroups(parentGroup);
+ }
+
+ this.store.toggleSubGroups(parentGroup);
+ },
+ leaveGroup(group, collection) {
+ this.service.leaveGroup(group.leavePath)
+ .then((response) => {
+ $.scrollTo(0);
+
+ this.store.removeGroup(group, collection);
+
+ // eslint-disable-next-line no-new
+ new Flash(response.json().notice, 'notice');
+ })
+ .catch((response) => {
+ let message = 'An error occurred. Please try again.';
+
+ if (response.status === 403) {
+ message = 'Failed to leave the group. Please make sure you are not the only owner';
+ }
+
+ // eslint-disable-next-line no-new
+ new Flash(message);
+ });
+ },
+ updateGroups(groups, parentGroup) {
+ this.store.setGroups(groups, parentGroup);
+ },
+ updatePagination(headers) {
+ this.store.storePagination(headers);
+ },
+ handleErrorResponse() {
+ this.isLoading = false;
+ $.scrollTo(0);
+
+ // eslint-disable-next-line no-new
+ new Flash('An error occurred. Please try again.');
+ },
+ },
+ created() {
+ eventHub.$on('fetchPage', this.fetchPage);
+ eventHub.$on('toggleSubGroups', this.toggleSubGroups);
+ eventHub.$on('leaveGroup', this.leaveGroup);
+ eventHub.$on('updateGroups', this.updateGroups);
+ eventHub.$on('updatePagination', this.updatePagination);
+ },
+ beforeMount() {
+ let groupFilterList = null;
+ const form = document.querySelector('form#group-filter-form');
+ const filter = document.querySelector('.js-groups-list-filter');
+ const holder = document.querySelector('.js-groups-list-holder');
+
+ const opts = {
+ form,
+ filter,
+ holder,
+ filterEndpoint: el.dataset.endpoint,
+ pagePath: el.dataset.path,
+ };
+
+ groupFilterList = new GroupFilterableList(opts);
+ groupFilterList.initSearch();
+ },
+ mounted() {
+ this.fetchGroups()
+ .then((response) => {
+ this.updatePagination(response.headers);
+ this.isLoading = false;
+ })
+ .catch(this.handleErrorResponse);
+ },
+ beforeDestroy() {
+ eventHub.$off('fetchPage', this.fetchPage);
+ eventHub.$off('toggleSubGroups', this.toggleSubGroups);
+ eventHub.$off('leaveGroup', this.leaveGroup);
+ eventHub.$off('updateGroups', this.updateGroups);
+ eventHub.$off('updatePagination', this.updatePagination);
+ },
+ });
+});
diff --git a/app/assets/javascripts/groups/services/groups_service.js b/app/assets/javascripts/groups/services/groups_service.js
new file mode 100644
index 00000000000..97e02fcb76d
--- /dev/null
+++ b/app/assets/javascripts/groups/services/groups_service.js
@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import VueResource from 'vue-resource';
+
+Vue.use(VueResource);
+
+export default class GroupsService {
+ constructor(endpoint) {
+ this.groups = Vue.resource(endpoint);
+ }
+
+ getGroups(parentId, page, filterGroups, sort) {
+ const data = {};
+
+ if (parentId) {
+ data.parent_id = parentId;
+ } else {
+ // Do not send the following param for sub groups
+ if (page) {
+ data.page = page;
+ }
+
+ if (filterGroups) {
+ data.filter_groups = filterGroups;
+ }
+
+ if (sort) {
+ data.sort = sort;
+ }
+ }
+
+ return this.groups.get(data);
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ leaveGroup(endpoint) {
+ return Vue.http.delete(endpoint);
+ }
+}
diff --git a/app/assets/javascripts/groups/stores/groups_store.js b/app/assets/javascripts/groups/stores/groups_store.js
new file mode 100644
index 00000000000..67ee7d140ce
--- /dev/null
+++ b/app/assets/javascripts/groups/stores/groups_store.js
@@ -0,0 +1,151 @@
+import Vue from 'vue';
+
+export default class GroupsStore {
+ constructor() {
+ this.state = {};
+ this.state.groups = {};
+ this.state.pageInfo = {};
+ }
+
+ setGroups(rawGroups, parent) {
+ const parentGroup = parent;
+ const tree = this.buildTree(rawGroups, parentGroup);
+
+ if (parentGroup) {
+ parentGroup.subGroups = tree;
+ } else {
+ this.state.groups = tree;
+ }
+
+ return tree;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ resetGroups(parent) {
+ const parentGroup = parent;
+ parentGroup.subGroups = {};
+ }
+
+ storePagination(pagination = {}) {
+ let paginationInfo;
+
+ if (Object.keys(pagination).length) {
+ const normalizedHeaders = gl.utils.normalizeHeaders(pagination);
+ paginationInfo = gl.utils.parseIntPagination(normalizedHeaders);
+ } else {
+ paginationInfo = pagination;
+ }
+
+ this.state.pageInfo = paginationInfo;
+ }
+
+ buildTree(rawGroups, parentGroup) {
+ const groups = this.decorateGroups(rawGroups);
+ const tree = {};
+ const mappedGroups = {};
+ const orphans = [];
+
+ // Map groups to an object
+ groups.map((group) => {
+ mappedGroups[group.id] = group;
+ mappedGroups[group.id].subGroups = {};
+ return group;
+ });
+
+ Object.keys(mappedGroups).map((key) => {
+ const currentGroup = mappedGroups[key];
+ if (currentGroup.parentId) {
+ // If the group is not at the root level, add it to its parent array of subGroups.
+ const findParentGroup = mappedGroups[currentGroup.parentId];
+ if (findParentGroup) {
+ mappedGroups[currentGroup.parentId].subGroups[currentGroup.id] = currentGroup;
+ mappedGroups[currentGroup.parentId].isOpen = true; // Expand group if it has subgroups
+ } else if (parentGroup && parentGroup.id === currentGroup.parentId) {
+ tree[currentGroup.id] = currentGroup;
+ } else {
+ // Means the groups hast no direct parent.
+ // Save for later processing, we will add them to its corresponding base group
+ orphans.push(currentGroup);
+ }
+ } else {
+ // If the group is at the root level, add it to first level elements array.
+ tree[currentGroup.id] = currentGroup;
+ }
+
+ return key;
+ });
+
+ // Hopefully this array will be empty for most cases
+ if (orphans.length) {
+ orphans.map((orphan) => {
+ let found = false;
+ const currentOrphan = orphan;
+
+ Object.keys(tree).map((key) => {
+ const group = tree[key];
+ if (currentOrphan.fullPath.lastIndexOf(group.fullPath) === 0) {
+ group.subGroups[currentOrphan.id] = currentOrphan;
+ group.isOpen = true;
+ currentOrphan.isOrphan = true;
+ found = true;
+ }
+
+ return key;
+ });
+
+ if (!found) {
+ currentOrphan.isOrphan = true;
+ tree[currentOrphan.id] = currentOrphan;
+ }
+
+ return orphan;
+ });
+ }
+
+ return tree;
+ }
+
+ decorateGroups(rawGroups) {
+ this.groups = rawGroups.map(this.decorateGroup);
+ return this.groups;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ decorateGroup(rawGroup) {
+ return {
+ id: rawGroup.id,
+ fullName: rawGroup.full_name,
+ fullPath: rawGroup.full_path,
+ avatarUrl: rawGroup.avatar_url,
+ name: rawGroup.name,
+ hasSubgroups: rawGroup.has_subgroups,
+ canEdit: rawGroup.can_edit,
+ description: rawGroup.description,
+ webUrl: rawGroup.web_url,
+ parentId: rawGroup.parent_id,
+ visibility: rawGroup.visibility,
+ leavePath: rawGroup.leave_path,
+ editPath: rawGroup.edit_path,
+ isOpen: false,
+ isOrphan: false,
+ numberProjects: rawGroup.number_projects_with_delimiter,
+ numberUsers: rawGroup.number_users_with_delimiter,
+ permissions: {
+ humanGroupAccess: rawGroup.permissions.human_group_access,
+ },
+ subGroups: {},
+ };
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ removeGroup(group, collection) {
+ Vue.delete(collection, group.id);
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ toggleSubGroups(toggleGroup) {
+ const group = toggleGroup;
+ group.isOpen = !group.isOpen;
+ return group;
+ }
+}
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index a537267643e..2aca86189fd 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -167,8 +167,8 @@
if the name does not exist this function will return `null`
otherwise it will return the value of the param key provided
*/
- w.gl.utils.getParameterByName = (name) => {
- const url = window.location.href;
+ w.gl.utils.getParameterByName = (name, parseUrl) => {
+ const url = parseUrl || window.location.href;
name = name.replace(/[[\]]/g, '\\$&');
const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`);
const results = regex.exec(url);
diff --git a/app/assets/javascripts/locale/bg/app.js b/app/assets/javascripts/locale/bg/app.js
new file mode 100644
index 00000000000..ba56c0bea25
--- /dev/null
+++ b/app/assets/javascripts/locale/bg/app.js
@@ -0,0 +1 @@
+var locales = locales || {}; locales['bg'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-05 09:40-0400","Last-Translator":"Lyubomir Vasilev <lyubomirv@abv.bg>","Language-Team":"Bulgarian","Language":"bg","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"bg","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"ByAuthor|by":["от"],"Commit":["Подаване","Подавания"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Анализът на циклите дава общ поглед върху това колко време е нужно на една идея да се превърне в завършена функционалност в проекта."],"CycleAnalyticsStage|Code":["Програмиране"],"CycleAnalyticsStage|Issue":["Проблем"],"CycleAnalyticsStage|Plan":["Планиране"],"CycleAnalyticsStage|Production":["Издаване"],"CycleAnalyticsStage|Review":["Преглед и одобрение"],"CycleAnalyticsStage|Staging":["Подготовка за издаване"],"CycleAnalyticsStage|Test":["Тестване"],"Deploy":["Внедряване","Внедрявания"],"FirstPushedBy|First":["Първо"],"FirstPushedBy|pushed by":["изпращане на промени от"],"From issue creation until deploy to production":["От създаването на проблема до внедряването в крайната версия"],"From merge request merge until deploy to production":["От прилагането на заявката за сливане до внедряването в крайната версия"],"Introducing Cycle Analytics":["Представяме Ви анализът на циклите"],"Last %d day":["Последния %d ден","Последните %d дни"],"Limited to showing %d event at most":["Ограничено до показване на последното %d събитие","Ограничено до показване на последните %d събития"],"Median":["Медиана"],"New Issue":["Нов проблем","Нови проблема"],"Not available":["Не е налично"],"Not enough data":["Няма достатъчно данни"],"OpenedNDaysAgo|Opened":["Отворен"],"Pipeline Health":["Състояние"],"ProjectLifecycle|Stage":["Етап"],"Read more":["Прочетете повече"],"Related Commits":["Свързани подавания"],"Related Deployed Jobs":["Свързани задачи за внедряване"],"Related Issues":["Свързани проблеми"],"Related Jobs":["Свързани задачи"],"Related Merge Requests":["Свързани заявки за сливане"],"Related Merged Requests":["Свързани приложени заявки за сливане"],"Showing %d event":["Показване на %d събитие","Показване на %d събития"],"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.":["Етапът на програмиране показва времето от първото подаване до създаването на заявката за сливане. Данните ще бъдат добавени тук автоматично след като бъде създадена първата заявка за сливане."],"The collection of events added to the data gathered for that stage.":["Съвкупността от събития добавени към данните събрани за този етап."],"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.":["Етапът на проблемите показва колко е времето от създаването на проблем до определянето на целеви етап на проекта за него, или до добавянето му в списък на дъската за проблеми. Започнете да добавяте проблеми, за да видите данните за този етап."],"The phase of the development lifecycle.":["Етапът от цикъла на разработка"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["Етапът на планиране показва колко е времето от преходната стъпка до изпращането на първото подаване. Това време ще бъде добавено автоматично след като изпратите първото си подаване."],"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.":["Етапът на издаване показва общото време, което е нужно от създаването на проблем до внедряването на кода в крайната версия."],"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.":["Етапът на преглед и одобрение показва времето от създаването на заявката за сливане до прилагането ѝ. Данните ще бъдат добавени автоматично след като приложите първата си заявка за сливане."],"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.":["Етапът на подготовка за издаване показва времето между прилагането на заявката за сливане и внедряването на кода в средата на работещата крайна версия. Данните ще бъдат добавени автоматично след като направите първото си внедряване в крайната версия."],"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.":["Етапът на тестване показва времето, което е нужно на „Gitlab CI“ да изпълни всички задачи за свързаната заявка за сливане. Данните ще бъдат добавени автоматично след като приключи изпълнените на първата Ви такава задача."],"The time taken by each data entry gathered by that stage.":["Времето, което отнема всеки запис от данни за съответния етап."],"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.":["Стойността, която се намира в средата на последователността от наблюдавани данни. Например: медианата на 3, 5 и 9 е 5, а медианата на 3, 5, 7 и 8 е (5+7)/2 = 6."],"Time before an issue gets scheduled":["Време преди един проблем да бъде планиран за работа"],"Time before an issue starts implementation":["Време преди работата по проблем да започне"],"Time between merge request creation and merge/close":["Време между създаване на заявка за сливане и прилагането/отхвърлянето ѝ"],"Time until first merge request":["Време преди първата заявка за сливане"],"Time|hr":["час","часа"],"Time|min":["мин","мин"],"Time|s":["сек"],"Total Time":["Общо време"],"Total test time for all commits/merges":["Общо време за тестване на всички подавания/сливания"],"Want to see the data? Please ask an administrator for access.":["Искате ли да видите данните? Помолете администратор за достъп."],"We don't have enough data to show this stage.":["Няма достатъчно данни за този етап."],"You need permission.":["Нуждаете се от разрешение."],"day":["ден","дни"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/de/app.js b/app/assets/javascripts/locale/de/app.js
index 960b8e5ecb3..5f6d9f01bf7 100644
--- a/app/assets/javascripts/locale/de/app.js
+++ b/app/assets/javascripts/locale/de/app.js
@@ -1 +1 @@
-var locales = locales || {}; locales['de'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-06-07 12:17+0200","Language-Team":"German","Language":"de","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"Bob Van Landuyt <bob@gitlab.com>","X-Generator":"Poedit 2.0.2","lang":"de","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":["Von"],"CI configuration":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["Commit","Commits"],"CommitMessage|Add %{file_name}":[""],"Commits":["Commits"],"Commits|History":["Commits"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":[""],"CreateNewFork|Fork":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics liefern einen Überblick darüber, wie viel Zeit in Ihrem Projekt von einer Idee bis zum Produktivdeployment vergeht."],"CycleAnalyticsStage|Code":["Code"],"CycleAnalyticsStage|Issue":["Issue"],"CycleAnalyticsStage|Plan":["Planung"],"CycleAnalyticsStage|Production":["Produktiv"],"CycleAnalyticsStage|Review":["Review"],"CycleAnalyticsStage|Staging":["Staging"],"CycleAnalyticsStage|Test":["Test"],"Deploy":["Deployment","Deployments"],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Files":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["Erster"],"FirstPushedBy|pushed by":["gepusht von"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["Vom Anlegen des Issues bis zum Produktivdeployment"],"From merge request merge until deploy to production":["Vom Merge Request bis zum Produktivdeployment"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Introducing Cycle Analytics":["Was sind Cycle Analytics?"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["Letzter %d Tag","Letzten %d Tage"],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["Eingeschränkt auf maximal %d Ereignis","Eingeschränkt auf maximal %d Ereignisse"],"Median":["Median"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["Neues Issue","Neue Issues"],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["Neues Issue"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"Not available":["Nicht verfügbar"],"Not enough data":["Nicht genügend Daten"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["Erstellt"],"Pipeline Health":["Pipeline Kennzahlen"],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["Phase"],"ProjectNetworkGraph|Graph":[""],"Read more":["Mehr"],"Readme":[""],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["Zugehörige Commits"],"Related Deployed Jobs":["Zugehörige Deploymentjobs"],"Related Issues":["Zugehörige Issues"],"Related Jobs":["Zugehörige Jobs"],"Related Merge Requests":["Zugehörige Merge Requests"],"Related Merged Requests":["Zugehörige abgeschlossene Merge Requests"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["Zeige %d Ereignis","Zeige %d Ereignisse"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"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.":["Die Code-Phase stellt die Zeit vom ersten Commit bis zum Erstellen eines Merge Requests dar. Sobald Sie Ihren ersten Merge Request anlegen, werden dessen Daten automatisch ergänzt."],"The collection of events added to the data gathered for that stage.":["Ereignisse, die für diese Phase ausgewertet wurden."],"The fork relationship has been removed.":[""],"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.":["Die Issue-Phase stellt die Zeit vom Anlegen eines Issues bis zum Zuweisen eines Meilensteins oder Hinzufügen zum Issue Board dar. Erstellen Sie einen Issue, damit dessen Daten hier erscheinen."],"The phase of the development lifecycle.":["Die Phase im Entwicklungsprozess."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["Die Planungsphase stellt die Zeit von der vorherigen Phase bis zum Pushen des ersten Commits dar. Sobald Sie den ersten Commit pushen, werden dessen Daten hier erscheinen."],"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.":["Die Produktiv-Phase stellt die Gesamtzeit vom Anlegen eines Issues bis zum Deployment auf dem Produktivsystem dar. Sobald Sie den vollständigen Entwicklungszyklus von einer Idee bis zum Produktivdeployment durchlaufen haben, erscheinen die zugehörigen Daten hier."],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["Die Review-Phase stellt die Zeit vom Anlegen eines Merge Requests bis zum Mergen dar. Sobald Sie Ihren ersten Merge Request abschließen, werden dessen Daten hier automatisch angezeigt."],"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.":["Die Staging-Phase stellt die Zeit zwischen Mergen eines Merge Requests und dem Produktivdeployment dar. Sobald Sie das erste Produktivdeployment durchgeführt haben, werden dessen Daten hier automatisch angezeigt."],"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.":["Die Test-Phase stellt die Zeit dar, die GitLab CI benötigt um die Pipelines von Merge Requests abzuarbeiten. Sobald die erste Pipeline abgeschlossen ist, werden deren Daten hier automatisch angezeigt."],"The time taken by each data entry gathered by that stage.":["Zeit die für das jeweilige Ereignis in der Phase ermittelt wurde."],"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.":["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."],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["Zeit bis ein Issue geplant wird"],"Time before an issue starts implementation":["Zeit bis die Implementierung für ein Issue beginnt"],"Time between merge request creation and merge/close":["Zeit zwischen Anlegen und Mergen/Schließen eines Merge Requests"],"Time until first merge request":["Zeit bis zum ersten Merge Request"],"Timeago|%s days ago":[""],"Timeago|%s days remaining":[""],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":[""],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":[""],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":[""],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":[""],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["h","h"],"Time|min":["min","min"],"Time|s":["s"],"Total Time":["Gesamtzeit"],"Total test time for all commits/merges":["Gesamte Testlaufzeit für alle Commits/Merges"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["Um diese Daten einsehen zu können, wenden Sie sich bitte an Ihren Administrator."],"We don't have enough data to show this stage.":["Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["Sie benötigen Zugriffsrechte."],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["Tag","Tage"],"notification emails":[""]}}}; \ No newline at end of file
+var locales = locales || {}; locales['de'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-09 13:44+0200","Language-Team":"German","Language":"de","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"","X-Generator":"Poedit 2.0.1","lang":"de","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":["Von"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["Commit","Commits"],"CommitMessage|Add %{file_name}":["Commit\u0000Commits"],"Commits":["Commit\u0000Commits"],"Commits|History":["Commit\u0000Commits"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["Zugehörige Merge Requests"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics liefern einen Überblick darüber, wie viel Zeit in Ihrem Projekt von einer Idee bis zum Produktivdeployment vergeht."],"CycleAnalyticsStage|Code":["Code"],"CycleAnalyticsStage|Issue":["Issue"],"CycleAnalyticsStage|Plan":["Planung"],"CycleAnalyticsStage|Production":["Produktiv"],"CycleAnalyticsStage|Review":["Review"],"CycleAnalyticsStage|Staging":["Staging"],"CycleAnalyticsStage|Test":["Test"],"Delete":[""],"Deploy":["Deployment","Deployments"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["Erster"],"FirstPushedBy|pushed by":["gepusht von"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["Vom Anlegen des Issues bis zum Produktivdeployment"],"From merge request merge until deploy to production":["Vom Merge Request bis zum Produktivdeployment"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["Was sind Cycle Analytics?"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["Letzter %d Tag","Letzten %d Tage"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["Eingeschränkt auf maximal %d Ereignis","Eingeschränkt auf maximal %d Ereignisse"],"Median":["Median"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["Neues Issue","Neue Issues"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["Neues Issue\u0000Neue Issues"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["Nicht verfügbar"],"Not enough data":["Nicht genügend Daten"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["Erstellt"],"Owner":[""],"Pipeline Health":["Pipeline Kennzahlen"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["Phase"],"ProjectNetworkGraph|Graph":[""],"Read more":["Mehr"],"Readme":["Mehr"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["Zugehörige Commits"],"Related Deployed Jobs":["Zugehörige Deploymentjobs"],"Related Issues":["Zugehörige Issues"],"Related Jobs":["Zugehörige Jobs"],"Related Merge Requests":["Zugehörige Merge Requests"],"Related Merged Requests":["Zugehörige abgeschlossene Merge Requests"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["Zeige %d Ereignis","Zeige %d Ereignisse"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"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.":["Die Code-Phase stellt die Zeit vom ersten Commit bis zum Erstellen eines Merge Requests dar. Sobald Sie Ihren ersten Merge Request anlegen, werden dessen Daten automatisch ergänzt."],"The collection of events added to the data gathered for that stage.":["Ereignisse, die für diese Phase ausgewertet wurden."],"The fork relationship has been removed.":[""],"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.":["Die Issue-Phase stellt die Zeit vom Anlegen eines Issues bis zum Zuweisen eines Meilensteins oder Hinzufügen zum Issue Board dar. Erstellen Sie einen Issue, damit dessen Daten hier erscheinen."],"The phase of the development lifecycle.":["Die Phase im Entwicklungsprozess."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["Die Planungsphase stellt die Zeit von der vorherigen Phase bis zum Pushen des ersten Commits dar. Sobald Sie den ersten Commit pushen, werden dessen Daten hier erscheinen."],"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.":["Die Produktiv-Phase stellt die Gesamtzeit vom Anlegen eines Issues bis zum Deployment auf dem Produktivsystem dar. Sobald Sie den vollständigen Entwicklungszyklus von einer Idee bis zum Produktivdeployment durchlaufen haben, erscheinen die zugehörigen Daten hier."],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["Die Review-Phase stellt die Zeit vom Anlegen eines Merge Requests bis zum Mergen dar. Sobald Sie Ihren ersten Merge Request abschließen, werden dessen Daten hier automatisch angezeigt."],"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.":["Die Staging-Phase stellt die Zeit zwischen Mergen eines Merge Requests und dem Produktivdeployment dar. Sobald Sie das erste Produktivdeployment durchgeführt haben, werden dessen Daten hier automatisch angezeigt."],"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.":["Die Test-Phase stellt die Zeit dar, die GitLab CI benötigt um die Pipelines von Merge Requests abzuarbeiten. Sobald die erste Pipeline abgeschlossen ist, werden deren Daten hier automatisch angezeigt."],"The time taken by each data entry gathered by that stage.":["Zeit die für das jeweilige Ereignis in der Phase ermittelt wurde."],"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.":["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."],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["Zeit bis ein Issue geplant wird"],"Time before an issue starts implementation":["Zeit bis die Implementierung für ein Issue beginnt"],"Time between merge request creation and merge/close":["Zeit zwischen Anlegen und Mergen/Schließen eines Merge Requests"],"Time until first merge request":["Zeit bis zum ersten Merge Request"],"Timeago|%s days ago":["Tag\u0000Tage"],"Timeago|%s days remaining":["Tag\u0000Tage"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["Tag\u0000Tage"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["Tag\u0000Tage"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["Tag\u0000Tage"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["Tag\u0000Tage"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["h","h"],"Time|min":["min","min"],"Time|s":["s"],"Total Time":["Gesamtzeit"],"Total test time for all commits/merges":["Gesamte Testlaufzeit für alle Commits/Merges"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["Um diese Daten einsehen zu können, wenden Sie sich bitte an Ihren Administrator."],"We don't have enough data to show this stage.":["Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["Sie benötigen Zugriffsrechte."],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["Tag","Tage"],"notification emails":[""]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/en/app.js b/app/assets/javascripts/locale/en/app.js
index 80203308b00..774dc2f094f 100644
--- a/app/assets/javascripts/locale/en/app.js
+++ b/app/assets/javascripts/locale/en/app.js
@@ -1 +1 @@
-var locales = locales || {}; locales['en'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-06-07 12:14+0200","Language-Team":"English","Language":"en","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"Bob Van Landuyt <bob@gitlab.com>","X-Generator":"Poedit 2.0.2","lang":"en","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":[""],"CI configuration":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["",""],"CommitMessage|Add %{file_name}":[""],"Commits":[""],"Commits|History":[""],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":[""],"CreateNewFork|Fork":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":[""],"CycleAnalyticsStage|Code":[""],"CycleAnalyticsStage|Issue":[""],"CycleAnalyticsStage|Plan":[""],"CycleAnalyticsStage|Production":[""],"CycleAnalyticsStage|Review":[""],"CycleAnalyticsStage|Staging":[""],"CycleAnalyticsStage|Test":[""],"Deploy":["",""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Files":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":[""],"FirstPushedBy|pushed by":[""],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":[""],"From merge request merge until deploy to production":[""],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Introducing Cycle Analytics":[""],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["",""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["",""],"Median":[""],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["",""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":[""],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"Not available":[""],"Not enough data":[""],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":[""],"Pipeline Health":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":[""],"ProjectNetworkGraph|Graph":[""],"Read more":[""],"Readme":[""],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":[""],"Related Deployed Jobs":[""],"Related Issues":[""],"Related Jobs":[""],"Related Merge Requests":[""],"Related Merged Requests":[""],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["",""],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"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.":[""],"The collection of events added to the data gathered for that stage.":[""],"The fork relationship has been removed.":[""],"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.":[""],"The phase of the development lifecycle.":[""],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":[""],"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.":[""],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":[""],"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.":[""],"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.":[""],"The time taken by each data entry gathered by that stage.":[""],"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.":[""],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":[""],"Time before an issue starts implementation":[""],"Time between merge request creation and merge/close":[""],"Time until first merge request":[""],"Timeago|%s days ago":[""],"Timeago|%s days remaining":[""],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":[""],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":[""],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":[""],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":[""],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["",""],"Time|min":["",""],"Time|s":[""],"Total Time":[""],"Total test time for all commits/merges":[""],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":[""],"We don't have enough data to show this stage.":[""],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":[""],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["",""],"notification emails":[""]}}}; \ No newline at end of file
+var locales = locales || {}; locales['en'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-04-12 22:36-0500","Last-Translator":"FULL NAME <EMAIL@ADDRESS>","Language-Team":"English","Language":"en","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","lang":"en","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":[""],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["",""],"CommitMessage|Add %{file_name}":[""],"Commits":[""],"Commits|History":[""],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":[""],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":[""],"CycleAnalyticsStage|Code":[""],"CycleAnalyticsStage|Issue":[""],"CycleAnalyticsStage|Plan":[""],"CycleAnalyticsStage|Production":[""],"CycleAnalyticsStage|Review":[""],"CycleAnalyticsStage|Staging":[""],"CycleAnalyticsStage|Test":[""],"Delete":[""],"Deploy":["",""],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":[""],"FirstPushedBy|pushed by":[""],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":[""],"From merge request merge until deploy to production":[""],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":[""],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["",""],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["",""],"Median":[""],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["",""],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":[""],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":[""],"Not enough data":[""],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":[""],"Owner":[""],"Pipeline Health":[""],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":[""],"ProjectNetworkGraph|Graph":[""],"Read more":[""],"Readme":[""],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":[""],"Related Deployed Jobs":[""],"Related Issues":[""],"Related Jobs":[""],"Related Merge Requests":[""],"Related Merged Requests":[""],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["",""],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"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.":[""],"The collection of events added to the data gathered for that stage.":[""],"The fork relationship has been removed.":[""],"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.":[""],"The phase of the development lifecycle.":[""],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":[""],"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.":[""],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":[""],"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.":[""],"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.":[""],"The time taken by each data entry gathered by that stage.":[""],"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.":[""],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":[""],"Time before an issue starts implementation":[""],"Time between merge request creation and merge/close":[""],"Time until first merge request":[""],"Timeago|%s days ago":[""],"Timeago|%s days remaining":[""],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":[""],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":[""],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":[""],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":[""],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["",""],"Time|min":["",""],"Time|s":[""],"Total Time":[""],"Total test time for all commits/merges":[""],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":[""],"We don't have enough data to show this stage.":[""],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":[""],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["",""],"notification emails":[""]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/es/app.js b/app/assets/javascripts/locale/es/app.js
index 6977625f4d8..0fbe4ada8fa 100644
--- a/app/assets/javascripts/locale/es/app.js
+++ b/app/assets/javascripts/locale/es/app.js
@@ -1 +1 @@
-var locales = locales || {}; locales['es'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-06-07 12:29-0500","Language-Team":"Spanish","Language":"es","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"Bob Van Landuyt <bob@gitlab.com>","X-Generator":"Poedit 2.0.2","lang":"es","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":["Acerca del auto despliegue"],"Activity":["Actividad"],"Add Changelog":["Agregar Changelog"],"Add Contribution guide":["Agregar guía de contribución"],"Add License":["Agregar Licencia"],"Add an SSH key to your profile to pull or push via SSH.":["Agregar una clave SSH a tu perfil para actualizar o enviar a través de SSH."],"Add new directory":["Agregar nuevo directorio"],"Archived project! Repository is read-only":["¡Proyecto archivado! El repositorio es de sólo lectura"],"Branch":["Rama","Ramas"],"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}":["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}"],"Branches":["Ramas"],"ByAuthor|by":["por"],"CI configuration":["Configuración de CI"],"Changelog":["Changelog"],"Charts":["Gráficos"],"CiStatusLabel|canceled":["cancelado"],"CiStatusLabel|created":["creado"],"CiStatusLabel|failed":["fallado"],"CiStatusLabel|manual action":["acción manual"],"CiStatusLabel|passed":["pasó"],"CiStatusLabel|passed with warnings":["pasó con advertencias"],"CiStatusLabel|pending":["pendiente"],"CiStatusLabel|skipped":["omitido"],"CiStatusLabel|waiting for manual action":["esperando acción manual"],"CiStatusText|blocked":["bloqueado"],"CiStatusText|canceled":["cancelado"],"CiStatusText|created":["creado"],"CiStatusText|failed":["fallado"],"CiStatusText|manual":["manual"],"CiStatusText|passed":["pasó"],"CiStatusText|pending":["pendiente"],"CiStatusText|skipped":["omitido"],"CiStatus|running":["en ejecución"],"Commit":["Cambio","Cambios"],"CommitMessage|Add %{file_name}":["Agregar %{file_name}"],"Commits":["Cambios"],"Commits|History":["Historial"],"Compare":["Comparar"],"Contribution guide":["Guía de contribución"],"Contributors":["Contribuidores"],"Copy URL to clipboard":["Copiar URL al portapapeles"],"Copy commit SHA to clipboard":["Copiar SHA del cambio al portapapeles"],"Create New Directory":["Crear Nuevo Directorio"],"Create directory":["Crear directorio"],"Create empty bare repository":["Crear repositorio vacío"],"Create merge request":["Crear solicitud de fusión"],"CreateNewFork|Fork":["Bifurcar"],"Custom notification events":["Eventos de notificaciones personalizadas"],"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}.":["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}."],"Cycle Analytics":["Cycle Analytics"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics ofrece una visión general de cuánto tiempo tarda en pasar de idea a producción en su proyecto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Incidencia"],"CycleAnalyticsStage|Plan":["Planificación"],"CycleAnalyticsStage|Production":["Producción"],"CycleAnalyticsStage|Review":["Revisión"],"CycleAnalyticsStage|Staging":["Puesta en escena"],"CycleAnalyticsStage|Test":["Pruebas"],"Deploy":["Despliegue","Despliegues"],"Directory name":["Nombre del directorio"],"Don't show again":["No mostrar de nuevo"],"Download tar":["Descargar tar"],"Download tar.bz2":["Descargar tar.bz2"],"Download tar.gz":["Descargar tar.gz"],"Download zip":["Descargar zip"],"DownloadArtifacts|Download":["Descargar"],"DownloadSource|Download":["Descargar"],"Files":["Archivos"],"Find by path":["Buscar por ruta"],"Find file":["Buscar archivo"],"FirstPushedBy|First":["Primer"],"FirstPushedBy|pushed by":["enviado por"],"ForkedFromProjectPath|Forked from":["Bifurcado de"],"Forks":["Bifurcaciones"],"From issue creation until deploy to production":["Desde la creación de la incidencia hasta el despliegue a producción"],"From merge request merge until deploy to production":["Desde la integración de la solicitud de fusión hasta el despliegue a producción"],"Go to your fork":["Ir a tu bifurcación"],"GoToYourFork|Fork":["Bifurcación"],"Home":["Inicio"],"Housekeeping successfully started":["Servicio de limpieza iniciado con éxito"],"Import repository":["Importar repositorio"],"Introducing Cycle Analytics":["Introducción a Cycle Analytics"],"LFSStatus|Disabled":["Deshabilitado"],"LFSStatus|Enabled":["Habilitado"],"Last %d day":["Último %d día","Últimos %d días"],"Last Update":["Última actualización"],"Last commit":["Último cambio"],"Leave group":["Abandonar grupo"],"Leave project":["Abandonar proyecto"],"Limited to showing %d event at most":["Limitado a mostrar máximo %d evento","Limitado a mostrar máximo %d eventos"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":["agregar una clave SSH"],"New Issue":["Nueva incidencia","Nuevas incidencias"],"New branch":["Nueva rama"],"New directory":["Nuevo directorio"],"New file":["Nuevo archivo"],"New issue":["Nueva incidencia"],"New merge request":["Nueva solicitud de fusión"],"New snippet":["Nuevo fragmento de código"],"New tag":["Nueva etiqueta"],"No repository":["No hay repositorio"],"Not available":["No disponible"],"Not enough data":["No hay suficientes datos"],"Notification events":["Eventos de notificación"],"NotificationEvent|Close issue":["Cerrar incidencia"],"NotificationEvent|Close merge request":["Cerrar solicitud de fusión"],"NotificationEvent|Failed pipeline":["Pipeline fallido"],"NotificationEvent|Merge merge request":["Integrar solicitud de fusión"],"NotificationEvent|New issue":["Nueva incidencia"],"NotificationEvent|New merge request":["Nueva solicitud de fusión"],"NotificationEvent|New note":["Nueva nota"],"NotificationEvent|Reassign issue":["Reasignar incidencia"],"NotificationEvent|Reassign merge request":["Reasignar solicitud de fusión"],"NotificationEvent|Reopen issue":["Reabrir incidencia"],"NotificationEvent|Successful pipeline":["Pipeline exitoso"],"NotificationLevel|Custom":["Personalizado"],"NotificationLevel|Disabled":["Deshabilitado"],"NotificationLevel|Global":["Global"],"NotificationLevel|On mention":["Cuando me mencionan"],"NotificationLevel|Participate":["Participación"],"NotificationLevel|Watch":["Vigilancia"],"OpenedNDaysAgo|Opened":["Abierto"],"Pipeline Health":["Estado del Pipeline"],"Project '%{project_name}' queued for deletion.":["Proyecto ‘%{project_name}’ en cola para eliminación."],"Project '%{project_name}' was successfully created.":["Proyecto ‘%{project_name}’ fue creado satisfactoriamente."],"Project '%{project_name}' was successfully updated.":["Proyecto ‘%{project_name}’ fue actualizado satisfactoriamente."],"Project '%{project_name}' will be deleted.":["Proyecto ‘%{project_name}’ será eliminado."],"Project access must be granted explicitly to each user.":["El acceso al proyecto debe concederse explícitamente a cada usuario."],"Project export could not be deleted.":["No se pudo eliminar la exportación del proyecto."],"Project export has been deleted.":["La exportación del proyecto ha sido eliminada."],"Project export link has expired. Please generate a new export from your project settings.":["El enlace de exportación del proyecto ha caducado. Por favor, genera una nueva exportación desde la configuración del proyecto."],"Project export started. A download link will be sent by email.":["Se inició la exportación del proyecto. Se enviará un enlace de descarga por correo electrónico."],"Project home":["Inicio del proyecto"],"ProjectFeature|Disabled":["Deshabilitada"],"ProjectFeature|Everyone with access":["Todos con acceso"],"ProjectFeature|Only team members":["Solo miembros del equipo"],"ProjectFileTree|Name":["Nombre"],"ProjectLastActivity|Never":["Nunca"],"ProjectLifecycle|Stage":["Etapa"],"ProjectNetworkGraph|Graph":["Historial gráfico"],"Read more":["Leer más"],"Readme":["Readme"],"RefSwitcher|Branches":["Ramas"],"RefSwitcher|Tags":["Etiquetas"],"Related Commits":["Cambios Relacionados"],"Related Deployed Jobs":["Trabajos Desplegados Relacionados"],"Related Issues":["Incidencias Relacionadas"],"Related Jobs":["Trabajos Relacionados"],"Related Merge Requests":["Solicitudes de fusión Relacionadas"],"Related Merged Requests":["Solicitudes de fusión Relacionadas"],"Remind later":["Recordar después"],"Remove project":["Eliminar proyecto"],"Request Access":["Solicitar acceso"],"Search branches and tags":["Buscar ramas y etiquetas"],"Select Archive Format":["Seleccionar formato de archivo"],"Set a password on your account to pull or push via %{protocol}":["Establezca una contraseña en su cuenta para actualizar o enviar a través de% {protocol}"],"Set up CI":["Configurar CI"],"Set up Koding":["Configurar Koding"],"Set up auto deploy":["Configurar auto despliegue"],"SetPasswordToCloneLink|set a password":["establecer una contraseña"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":["Código fuente"],"StarProject|Star":["Destacar"],"Switch branch/tag":["Cambiar rama/etiqueta"],"Tag":["Etiqueta","Etiquetas"],"Tags":["Etiquetas"],"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.":["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."],"The collection of events added to the data gathered for that stage.":["La colección de eventos agregados a los datos recopilados para esa etapa."],"The fork relationship has been removed.":["La relación con la bifurcación se ha eliminado."],"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.":["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."],"The phase of the development lifecycle.":["La etapa del ciclo de vida de desarrollo."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["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."],"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.":["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."],"The project can be accessed by any logged in user.":["El proyecto puede ser accedido por cualquier usuario conectado."],"The project can be accessed without any authentication.":["El proyecto puede accederse sin ninguna autenticación."],"The repository for this project does not exist.":["El repositorio para este proyecto no existe."],"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.":["La etapa de revisión muestra el tiempo desde la creación de la solicitud de fusión hasta que los cambios se fusionaron. Los datos se añadirán automáticamente después de fusionar su primera solicitud de fusión."],"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.":["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."],"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.":["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."],"The time taken by each data entry gathered by that stage.":["El tiempo utilizado por cada entrada de datos obtenido por esa etapa."],"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.":["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."],"This means you can not push code until you create an empty repository or import existing one.":["Esto significa que no puede enviar código hasta que cree un repositorio vacío o importe uno existente."],"Time before an issue gets scheduled":["Tiempo antes de que una incidencia sea programada"],"Time before an issue starts implementation":["Tiempo antes de que empieze la implementación de una incidencia"],"Time between merge request creation and merge/close":["Tiempo entre la creación de la solicitud de fusión y la integración o cierre de ésta"],"Time until first merge request":["Tiempo hasta la primera solicitud de fusión"],"Timeago|%s days ago":["hace %s días"],"Timeago|%s days remaining":["%s días restantes"],"Timeago|%s hours remaining":["%s horas restantes"],"Timeago|%s minutes ago":["hace %s minutos"],"Timeago|%s minutes remaining":["%s minutos restantes"],"Timeago|%s months ago":["hace %s meses"],"Timeago|%s months remaining":["%s meses restantes"],"Timeago|%s seconds remaining":["%s segundos restantes"],"Timeago|%s weeks ago":["hace %s semanas"],"Timeago|%s weeks remaining":["%s semanas restantes"],"Timeago|%s years ago":["hace %s años"],"Timeago|%s years remaining":["%s años restantes"],"Timeago|1 day remaining":["1 día restante"],"Timeago|1 hour remaining":["1 hora restante"],"Timeago|1 minute remaining":["1 minuto restante"],"Timeago|1 month remaining":["1 mes restante"],"Timeago|1 week remaining":["1 semana restante"],"Timeago|1 year remaining":["1 año restante"],"Timeago|Past due":["Atrasado"],"Timeago|a day ago":["hace un día"],"Timeago|a month ago":["hace 1 mes"],"Timeago|a week ago":["hace 1 semana"],"Timeago|a while":["hace un momento"],"Timeago|a year ago":["hace 1 año"],"Timeago|about %s hours ago":["hace alrededor de %s horas"],"Timeago|about a minute ago":["hace alrededor de 1 minuto"],"Timeago|about an hour ago":["hace alrededor de 1 hora"],"Timeago|in %s days":["en %s días"],"Timeago|in %s hours":["en %s horas"],"Timeago|in %s minutes":["en %s minutos"],"Timeago|in %s months":["en %s meses"],"Timeago|in %s seconds":["en %s segundos"],"Timeago|in %s weeks":["en %s semanas"],"Timeago|in %s years":["en %s años"],"Timeago|in 1 day":["en 1 día"],"Timeago|in 1 hour":["en 1 hora"],"Timeago|in 1 minute":["en 1 minuto"],"Timeago|in 1 month":["en 1 mes"],"Timeago|in 1 week":["en 1 semana"],"Timeago|in 1 year":["en 1 año"],"Timeago|less than a minute ago":["hace menos de 1 minuto"],"Time|hr":["hr","hrs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tiempo Total"],"Total test time for all commits/merges":["Tiempo total de pruebas para todos los cambios o integraciones"],"Unstar":["No Destacar"],"Upload New File":["Subir nuevo archivo"],"Upload file":["Subir archivo"],"Use your global notification setting":["Utiliza tu configuración de notificación global"],"VisibilityLevel|Internal":["Interno"],"VisibilityLevel|Private":["Privado"],"VisibilityLevel|Public":["Público"],"Want to see the data? Please ask an administrator for access.":["¿Quieres ver los datos? Por favor pide acceso al administrador."],"We don't have enough data to show this stage.":["No hay suficientes datos para mostrar en esta etapa."],"Withdraw Access Request":["Retirar Solicitud de Acceso"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Va a eliminar %{project_name_with_namespace}.\\n¡El proyecto eliminado NO puede ser restaurado!\\n¿Estás TOTALMENTE seguro?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Vas a eliminar el enlace de la bifurcación con el proyecto original %{forked_from_project}. ¿Estás TOTALMENTE seguro?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Vas a transferir %{project_name_with_namespace} a otro propietario. ¿Estás TOTALMENTE seguro?"],"You can only add files when you are on a branch":["Sólo puede agregar archivos cuando estas en una rama"],"You must sign in to star a project":["Debes iniciar sesión para destacar un proyecto"],"You need permission.":["Necesitas permisos."],"You will not get any notifications via email":["No recibirás ninguna notificación por correo electrónico"],"You will only receive notifications for the events you choose":["Solo recibirás notificaciones de los eventos que elijas"],"You will only receive notifications for threads you have participated in":["Solo recibirás notificaciones de los temas en los que has participado"],"You will receive notifications for any activity":["Recibirás notificaciones para cualquier actividad"],"You will receive notifications only for comments in which you were @mentioned":["Recibirás notificaciones sólo para los comentarios en los que se te mencionó"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["No podrás actualizar o enviar código al proyecto a través de %{protocol} hasta que %{set_password_link} en tu cuenta"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["No podrás actualizar o enviar código al proyecto a través de SSH hasta que %{add_ssh_key_link} en su perfil"],"Your name":["Tu nombre"],"committed":["cambió"],"day":["día","días"],"notification emails":["correos electrónicos de notificación"]}}}; \ No newline at end of file
+var locales = locales || {}; locales['es'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-20 22:37-0500","Language-Team":"Spanish","Language":"es","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"","X-Generator":"Poedit 2.0.1","lang":"es","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":["por"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["Cambio","Cambios"],"CommitMessage|Add %{file_name}":["Cambio\u0000Cambios"],"Commits":["Cambio\u0000Cambios"],"Commits|History":["Cambio\u0000Cambios"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["Solicitudes de fusión Relacionadas"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics ofrece una visión general de cuánto tiempo tarda en pasar de idea a producción en su proyecto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Incidencia"],"CycleAnalyticsStage|Plan":["Planificación"],"CycleAnalyticsStage|Production":["Producción"],"CycleAnalyticsStage|Review":["Revisión"],"CycleAnalyticsStage|Staging":["Puesta en escena"],"CycleAnalyticsStage|Test":["Pruebas"],"Delete":[""],"Deploy":["Despliegue","Despliegues"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["Primer"],"FirstPushedBy|pushed by":["enviado por"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["Desde la creación de la incidencia hasta el despliegue a producción"],"From merge request merge until deploy to production":["Desde la integración de la solicitud de fusión hasta el despliegue a producción"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["Introducción a Cycle Analytics"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["Último %d día","Últimos %d días"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["Limitado a mostrar máximo %d evento","Limitado a mostrar máximo %d eventos"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["Nueva incidencia","Nuevas incidencias"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["Nueva incidencia\u0000Nuevas incidencias"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["No disponible"],"Not enough data":["No hay suficientes datos"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["Abierto"],"Owner":[""],"Pipeline Health":["Estado del Pipeline"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["Etapa"],"ProjectNetworkGraph|Graph":[""],"Read more":["Leer más"],"Readme":["Leer más"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["Cambios Relacionados"],"Related Deployed Jobs":["Trabajos Desplegados Relacionados"],"Related Issues":["Incidencias Relacionadas"],"Related Jobs":["Trabajos Relacionados"],"Related Merge Requests":["Solicitudes de fusión Relacionadas"],"Related Merged Requests":["Solicitudes de fusión Relacionadas"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"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.":["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."],"The collection of events added to the data gathered for that stage.":["La colección de eventos agregados a los datos recopilados para esa etapa."],"The fork relationship has been removed.":[""],"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.":["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."],"The phase of the development lifecycle.":["La etapa del ciclo de vida de desarrollo."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["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."],"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.":["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."],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["La etapa de revisión muestra el tiempo desde la creación de la solicitud de fusión hasta que los cambios se fusionaron. Los datos se añadirán automáticamente después de fusionar su primera solicitud de fusión."],"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.":["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."],"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.":["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."],"The time taken by each data entry gathered by that stage.":["El tiempo utilizado por cada entrada de datos obtenido por esa etapa."],"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.":["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."],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["Tiempo antes de que una incidencia sea programada"],"Time before an issue starts implementation":["Tiempo antes de que empieze la implementación de una incidencia"],"Time between merge request creation and merge/close":["Tiempo entre la creación de la solicitud de fusión y la integración o cierre de ésta"],"Time until first merge request":["Tiempo hasta la primera solicitud de fusión"],"Timeago|%s days ago":["día\u0000días"],"Timeago|%s days remaining":["día\u0000días"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["día\u0000días"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["día\u0000días"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["día\u0000días"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["día\u0000días"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["hr","hrs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tiempo Total"],"Total test time for all commits/merges":["Tiempo total de pruebas para todos los cambios o integraciones"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["¿Quieres ver los datos? Por favor pide acceso al administrador."],"We don't have enough data to show this stage.":["No hay suficientes datos para mostrar en esta etapa."],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["Necesitas permisos."],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["día","días"],"notification emails":[""]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/pt_BR/app.js b/app/assets/javascripts/locale/pt_BR/app.js
new file mode 100644
index 00000000000..f2eed3da064
--- /dev/null
+++ b/app/assets/javascripts/locale/pt_BR/app.js
@@ -0,0 +1 @@
+var locales = locales || {}; locales['pt_BR'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-05 03:29-0400","Last-Translator":"Alexandre Alencar <alexandre.alencar@gmail.com>","Language-Team":"Portuguese (Brazil)","Language":"pt-BR","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"pt_BR","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"ByAuthor|by":["por"],"Commit":["Commit","Commits"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Tarefa"],"CycleAnalyticsStage|Plan":["Plano"],"CycleAnalyticsStage|Production":["Produção"],"CycleAnalyticsStage|Review":["Revisão"],"CycleAnalyticsStage|Staging":["Homologação"],"CycleAnalyticsStage|Test":["Teste"],"Deploy":["Implantação","Implantações"],"FirstPushedBy|First":["Primeiro"],"FirstPushedBy|pushed by":["publicado por"],"From issue creation until deploy to production":["Da criação de tarefas até a implantação para a produção"],"From merge request merge until deploy to production":["Da incorporação do merge request até a implantação em produção"],"Introducing Cycle Analytics":["Apresentando a Análise de Ciclo"],"Last %d day":["Último %d dia","Últimos %d dias"],"Limited to showing %d event at most":["Limitado a mostrar %d evento no máximo","Limitado a mostrar %d eventos no máximo"],"Median":["Mediana"],"New Issue":["Nova Tarefa","Novas Tarefas"],"Not available":["Não disponível"],"Not enough data":["Dados insuficientes"],"OpenedNDaysAgo|Opened":["Aberto"],"Pipeline Health":["Saúde da Pipeline"],"ProjectLifecycle|Stage":["Etapa"],"Read more":["Ler mais"],"Related Commits":["Commits Relacionados"],"Related Deployed Jobs":["Jobs Relacionados Incorporados"],"Related Issues":["Tarefas Relacionadas"],"Related Jobs":["Jobs Relacionados"],"Related Merge Requests":["Merge Requests Relacionados"],"Related Merged Requests":["Merge Requests Relacionados"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"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.":["O estágio de codificação mostra o tempo desde o primeiro commit até a criação do merge request. \\nOs dados serão automaticamente adicionados aqui uma vez que você tenha criado seu primeiro merge request."],"The collection of events added to the data gathered for that stage.":["A coleção de eventos adicionados aos dados coletados para esse estágio."],"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.":["O estágio em questão mostra o tempo que leva desde a criação de uma tarefa até a sua assinatura para um milestone, ou a sua adição para a lista no seu Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa."],"The phase of the development lifecycle.":["A fase do ciclo de vida do desenvolvimento."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["A fase de planejamento mostra o tempo do passo anterior até empurrar o seu primeiro commit. Este tempo será adicionado automaticamente assim que você realizar seu primeiro commit."],"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.":["O estágio de produção mostra o tempo total que leva entre criar uma tarefa e implantar o código na produção. Os dados serão adicionados automaticamente até que você complete todo o ciclo de produção."],"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.":["A etapa de revisão mostra o tempo de criação de um merge request até que o merge seja feito. Os dados serão automaticamente adicionados depois que você fizer seu primeiro merge request."],"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.":["O estágio de estágio mostra o tempo entre a fusão do MR e o código de implantação para o ambiente de produção. Os dados serão automaticamente adicionados depois de implantar na produção pela primeira vez."],"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.":["A fase de teste mostra o tempo que o GitLab CI leva para executar cada pipeline para o merge request relacionado. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."],"The time taken by each data entry gathered by that stage.":["O tempo necessário para cada entrada de dados reunida por essa etapa."],"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.":["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."],"Time before an issue gets scheduled":["Tempo até que uma tarefa seja planejada"],"Time before an issue starts implementation":["Tempo até que uma tarefa comece a ser implementada"],"Time between merge request creation and merge/close":["Tempo entre a criação do merge request e o merge/fechamento"],"Time until first merge request":["Tempo até o primeiro merge request"],"Time|hr":["h","hs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tempo Total"],"Total test time for all commits/merges":["Tempo de teste total para todos os commits/merges"],"Want to see the data? Please ask an administrator for access.":["Precisa visualizar os dados? Solicite acesso ao administrador."],"We don't have enough data to show this stage.":["Não temos dados suficientes para mostrar esta fase."],"You need permission.":["Você precisa de permissão."],"day":["dia","dias"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/zh_CN/app.js b/app/assets/javascripts/locale/zh_CN/app.js
index 9525bc88190..2439fa931ef 100644
--- a/app/assets/javascripts/locale/zh_CN/app.js
+++ b/app/assets/javascripts/locale/zh_CN/app.js
@@ -1 +1 @@
-var locales = locales || {}; locales['zh_CN'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (China) (https://www.transifex.com/gitlab-zh/teams/75177/zh_CN/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_CN","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_CN","domain":"app","plural_forms":"nplurals=1; plural=0;"},"ByAuthor|by":["作者:"],"Commit":["提交"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["周期分析概述了项目从想法到产品实现的各阶段所需的时间。"],"CycleAnalyticsStage|Code":["编码"],"CycleAnalyticsStage|Issue":["议题"],"CycleAnalyticsStage|Plan":["计划"],"CycleAnalyticsStage|Production":["生产"],"CycleAnalyticsStage|Review":["评审"],"CycleAnalyticsStage|Staging":["预发布"],"CycleAnalyticsStage|Test":["测试"],"Deploy":["部署"],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["从创建议题到部署至生产环境"],"From merge request merge until deploy to production":["从合并请求被合并后到部署至生产环境"],"Introducing Cycle Analytics":["周期分析简介"],"Last %d day":["最后 %d 天"],"Limited to showing %d event at most":["最多显示 %d 个事件"],"Median":["中位数"],"New Issue":["新议题"],"Not available":["数据不足"],"Not enough data":["数据不足"],"OpenedNDaysAgo|Opened":["开始于"],"Pipeline Health":["流水线健康指标"],"ProjectLifecycle|Stage":["项目生命周期"],"Read more":["了解更多"],"Related Commits":["相关的提交"],"Related Deployed Jobs":["相关的部署作业"],"Related Issues":["相关的议题"],"Related Jobs":["相关的作业"],"Related Merge Requests":["相关的合并请求"],"Related Merged Requests":["相关已合并的合并请求"],"Showing %d event":["显示 %d 个事件"],"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.":["编码阶段概述了从第一次提交到创建合并请求的时间。创建第一个合并请求后,数据将自动添加到此处。"],"The collection of events added to the data gathered for that stage.":["与该阶段相关的事件。"],"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.":["议题阶段概述了从创建议题到将议题设置里程碑或将议题添加到议题看板的时间。开始创建议题以查看此阶段的数据。"],"The phase of the development lifecycle.":["项目生命周期中的各个阶段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["计划阶段概述了从议题添加到日程后到推送首次提交的时间。当首次推送提交后,数据将自动添加到此处。"],"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.":["生产阶段概述了从创建一个议题到将代码部署到生产环境的总时间。当完成想法到部署生产的循环,数据将自动添加到此处。"],"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.":["评审阶段概述了从创建合并请求到被合并的时间。当创建第一个合并请求后,数据将自动添加到此处。"],"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.":["预发布阶段概述了从合并请求被合并到部署至生产环境的总时间。首次部署到生产环境后,数据将自动添加到此处。"],"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.":["测试阶段概述了GitLab CI为相关合并请求运行每个流水线所需的时间。当第一个流水线运行完成后,数据将自动添加到此处。"],"The time taken by each data entry gathered by that stage.":["该阶段每条数据所花的时间"],"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.":["中位数是一个数列中最中间的值。例如在 3、5、9 之间,中位数是 5。在 3、5、7、8 之间,中位数是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["议题被列入日程表的时间"],"Time before an issue starts implementation":["开始进行编码前的时间"],"Time between merge request creation and merge/close":["从创建合并请求到被合并或关闭的时间"],"Time until first merge request":["创建第一个合并请求之前的时间"],"Time|hr":["小时"],"Time|min":["分钟"],"Time|s":["秒"],"Total Time":["总时间"],"Total test time for all commits/merges":["所有提交和合并的总测试时间"],"Want to see the data? Please ask an administrator for access.":["权限不足。如需查看相关数据,请向管理员申请权限。"],"We don't have enough data to show this stage.":["该阶段的数据不足,无法显示。"],"You need permission.":["您需要相关的权限。"],"day":["天"]}}}; \ No newline at end of file
+var locales = locales || {}; locales['zh_CN'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (China) (https://www.transifex.com/gitlab-zh/teams/75177/zh_CN/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_CN","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_CN","domain":"app","plural_forms":"nplurals=1; plural=0;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":["作者:"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["提交"],"CommitMessage|Add %{file_name}":["提交"],"Commits":["提交"],"Commits|History":["提交"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["相关的合并请求"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["周期分析概述了项目从想法到产品实现的各阶段所需的时间。"],"CycleAnalyticsStage|Code":["编码"],"CycleAnalyticsStage|Issue":["议题"],"CycleAnalyticsStage|Plan":["计划"],"CycleAnalyticsStage|Production":["生产"],"CycleAnalyticsStage|Review":["评审"],"CycleAnalyticsStage|Staging":["预发布"],"CycleAnalyticsStage|Test":["测试"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["从创建议题到部署至生产环境"],"From merge request merge until deploy to production":["从合并请求被合并后到部署至生产环境"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["周期分析简介"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["最后 %d 天"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["最多显示 %d 个事件"],"Median":["中位数"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["新议题"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["新议题"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["数据不足"],"Not enough data":["数据不足"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["开始于"],"Owner":[""],"Pipeline Health":["流水线健康指标"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["项目生命周期"],"ProjectNetworkGraph|Graph":[""],"Read more":["了解更多"],"Readme":["了解更多"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["相关的提交"],"Related Deployed Jobs":["相关的部署作业"],"Related Issues":["相关的议题"],"Related Jobs":["相关的作业"],"Related Merge Requests":["相关的合并请求"],"Related Merged Requests":["相关已合并的合并请求"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["显示 %d 个事件"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"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.":["编码阶段概述了从第一次提交到创建合并请求的时间。创建第一个合并请求后,数据将自动添加到此处。"],"The collection of events added to the data gathered for that stage.":["与该阶段相关的事件。"],"The fork relationship has been removed.":[""],"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.":["议题阶段概述了从创建议题到将议题设置里程碑或将议题添加到议题看板的时间。开始创建议题以查看此阶段的数据。"],"The phase of the development lifecycle.":["项目生命周期中的各个阶段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["计划阶段概述了从议题添加到日程后到推送首次提交的时间。当首次推送提交后,数据将自动添加到此处。"],"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.":["生产阶段概述了从创建一个议题到将代码部署到生产环境的总时间。当完成想法到部署生产的循环,数据将自动添加到此处。"],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["评审阶段概述了从创建合并请求到被合并的时间。当创建第一个合并请求后,数据将自动添加到此处。"],"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.":["预发布阶段概述了从合并请求被合并到部署至生产环境的总时间。首次部署到生产环境后,数据将自动添加到此处。"],"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.":["测试阶段概述了GitLab CI为相关合并请求运行每个流水线所需的时间。当第一个流水线运行完成后,数据将自动添加到此处。"],"The time taken by each data entry gathered by that stage.":["该阶段每条数据所花的时间"],"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.":["中位数是一个数列中最中间的值。例如在 3、5、9 之间,中位数是 5。在 3、5、7、8 之间,中位数是 (5 + 7)/ 2 = 6。"],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["议题被列入日程表的时间"],"Time before an issue starts implementation":["开始进行编码前的时间"],"Time between merge request creation and merge/close":["从创建合并请求到被合并或关闭的时间"],"Time until first merge request":["创建第一个合并请求之前的时间"],"Timeago|%s days ago":["天"],"Timeago|%s days remaining":["天"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["天"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["天"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["天"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["天"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["小时"],"Time|min":["分钟"],"Time|s":["秒"],"Total Time":["总时间"],"Total test time for all commits/merges":["所有提交和合并的总测试时间"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["权限不足。如需查看相关数据,请向管理员申请权限。"],"We don't have enough data to show this stage.":["该阶段的数据不足,无法显示。"],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["您需要相关的权限。"],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["天"],"notification emails":[""]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/zh_HK/app.js b/app/assets/javascripts/locale/zh_HK/app.js
index fd0bcd988c5..216b6286d93 100644
--- a/app/assets/javascripts/locale/zh_HK/app.js
+++ b/app/assets/javascripts/locale/zh_HK/app.js
@@ -1 +1 @@
-var locales = locales || {}; locales['zh_HK'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/75177/zh_HK/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_HK","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_HK","domain":"app","plural_forms":"nplurals=1; plural=0;"},"ByAuthor|by":["作者:"],"Commit":["提交"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了項目從想法到產品實現的各階段所需的時間。"],"CycleAnalyticsStage|Code":["編碼"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["生產"],"CycleAnalyticsStage|Review":["評審"],"CycleAnalyticsStage|Staging":["預發布"],"CycleAnalyticsStage|Test":["測試"],"Deploy":["部署"],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["從創建議題到部署到生產環境"],"From merge request merge until deploy to production":["從合併請求的合併到部署至生產環境"],"Introducing Cycle Analytics":["週期分析簡介"],"Last %d day":["最後 %d 天"],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"New Issue":["新議題"],"Not available":["不可用"],"Not enough data":["數據不足"],"OpenedNDaysAgo|Opened":["開始於"],"Pipeline Health":["流水線健康指標"],"ProjectLifecycle|Stage":["項目生命週期"],"Read more":["了解更多"],"Related Commits":["相關的提交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的合並請求"],"Showing %d event":["顯示 %d 個事件"],"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.":["編碼階段概述了從第一次提交到創建合併請求的時間。創建第壹個合並請求後,數據將自動添加到此處。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"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.":["議題階段概述了從創建議題到將議題設置裏程碑或將議題添加到議題看板的時間。創建一個議題後,數據將自動添加到此處。"],"The phase of the development lifecycle.":["項目生命週期中的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段概述了從議題添加到日程後到推送首次提交的時間。當首次推送提交後,數據將自動添加到此處。"],"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.":["生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完成完整的想法到部署生產,數據將自動添加到此處。"],"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.":["評審階段概述了從創建合並請求到合併的時間。當創建第壹個合並請求後,數據將自動添加到此處。"],"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.":["預發布階段概述了合並請求的合併到部署代碼到生產環境的總時間。當首次部署到生產環境後,數據將自動添加到此處。"],"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.":["測試階段概述了GitLab CI為相關合併請求運行每個流水線所需的時間。當第壹個流水線運行完成後,數據將自動添加到此處。"],"The time taken by each data entry gathered by that stage.":["該階段每條數據所花的時間"],"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.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["開始進行編碼前的時間"],"Time between merge request creation and merge/close":["從創建合併請求到被合並或關閉的時間"],"Time until first merge request":["創建第壹個合併請求之前的時間"],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有提交和合併的總測試時間"],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關數據,請向管理員申請權限。"],"We don't have enough data to show this stage.":["該階段的數據不足,無法顯示。"],"You need permission.":["您需要相關的權限。"],"day":["天"]}}}; \ No newline at end of file
+var locales = locales || {}; locales['zh_HK'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/75177/zh_HK/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_HK","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_HK","domain":"app","plural_forms":"nplurals=1; plural=0;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":["作者:"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["提交"],"CommitMessage|Add %{file_name}":["提交"],"Commits":["提交"],"Commits|History":["提交"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["相關的合併請求"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了項目從想法到產品實現的各階段所需的時間。"],"CycleAnalyticsStage|Code":["編碼"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["生產"],"CycleAnalyticsStage|Review":["評審"],"CycleAnalyticsStage|Staging":["預發布"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["從創建議題到部署到生產環境"],"From merge request merge until deploy to production":["從合併請求的合併到部署至生產環境"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["新議題"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["新議題"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["不可用"],"Not enough data":["數據不足"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["項目生命週期"],"ProjectNetworkGraph|Graph":[""],"Read more":["了解更多"],"Readme":["了解更多"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["相關的提交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的合並請求"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["顯示 %d 個事件"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"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.":["編碼階段概述了從第一次提交到創建合併請求的時間。創建第壹個合並請求後,數據將自動添加到此處。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"The fork relationship has been removed.":[""],"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.":["議題階段概述了從創建議題到將議題設置裏程碑或將議題添加到議題看板的時間。創建一個議題後,數據將自動添加到此處。"],"The phase of the development lifecycle.":["項目生命週期中的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段概述了從議題添加到日程後到推送首次提交的時間。當首次推送提交後,數據將自動添加到此處。"],"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.":["生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完成完整的想法到部署生產,數據將自動添加到此處。"],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["評審階段概述了從創建合並請求到合併的時間。當創建第壹個合並請求後,數據將自動添加到此處。"],"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.":["預發布階段概述了合並請求的合併到部署代碼到生產環境的總時間。當首次部署到生產環境後,數據將自動添加到此處。"],"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.":["測試階段概述了GitLab CI為相關合併請求運行每個流水線所需的時間。當第壹個流水線運行完成後,數據將自動添加到此處。"],"The time taken by each data entry gathered by that stage.":["該階段每條數據所花的時間"],"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.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["開始進行編碼前的時間"],"Time between merge request creation and merge/close":["從創建合併請求到被合並或關閉的時間"],"Time until first merge request":["創建第壹個合併請求之前的時間"],"Timeago|%s days ago":["天"],"Timeago|%s days remaining":["天"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["天"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["天"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["天"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["天"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有提交和合併的總測試時間"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關數據,請向管理員申請權限。"],"We don't have enough data to show this stage.":["該階段的數據不足,無法顯示。"],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["您需要相關的權限。"],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["天"],"notification emails":[""]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/zh_TW/app.js b/app/assets/javascripts/locale/zh_TW/app.js
index 79904d17bf6..6b5420015e8 100644
--- a/app/assets/javascripts/locale/zh_TW/app.js
+++ b/app/assets/javascripts/locale/zh_TW/app.js
@@ -1 +1 @@
-var locales = locales || {}; locales['zh_TW'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Taiwan) (https://www.transifex.com/gitlab-zh/teams/75177/zh_TW/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_TW","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_TW","domain":"app","plural_forms":"nplurals=1; plural=0;"},"ByAuthor|by":["作者:"],"Commit":["送交"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了你的專案從想法到產品實現,各階段所需的時間。"],"CycleAnalyticsStage|Code":["程式開發"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["上線"],"CycleAnalyticsStage|Review":["複閱"],"CycleAnalyticsStage|Staging":["預備"],"CycleAnalyticsStage|Test":["測試"],"Deploy":["部署"],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["從議題建立至線上部署"],"From merge request merge until deploy to production":["從請求被合併後至線上部署"],"Introducing Cycle Analytics":["週期分析簡介"],"Last %d day":["最後 %d 天"],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"New Issue":["新議題"],"Not available":["無法使用"],"Not enough data":["資料不足"],"OpenedNDaysAgo|Opened":["開始於"],"Pipeline Health":["流水線健康指標"],"ProjectLifecycle|Stage":["專案生命週期"],"Read more":["了解更多"],"Related Commits":["相關的送交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的請求"],"Showing %d event":["顯示 %d 個事件"],"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.":["程式開發階段顯示從第一次送交到建立合併請求的時間。建立第一個合併請求後,資料將自動填入。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"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.":["議題階段顯示從議題建立到設置里程碑、或將該議題加至議題看板的時間。建立第一個議題後,資料將自動填入。"],"The phase of the development lifecycle.":["專案開發生命週期的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段顯示從議題添加到日程後至推送第一個送交的時間。當第一次推送送交後,資料將自動填入。"],"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.":["上線階段顯示從建立一個議題到部署程式至線上的總時間。當完成從想法到產品實現的循環後,資料將自動填入。"],"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.":["複閱階段顯示從合併請求建立後至被合併的時間。當建立第一個合併請求後,資料將自動填入。"],"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.":["預備階段顯示從合併請求被合併後至部署上線的時間。當第一次部署上線後,資料將自動填入。"],"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.":["測試階段顯示相關合併請求的流水線所花的時間。當第一個流水線運作完畢後,資料將自動填入。"],"The time taken by each data entry gathered by that stage.":["每筆該階段相關資料所花的時間。"],"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.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["議題等待開始實作的時間"],"Time between merge request creation and merge/close":["合併請求被合併或是關閉的時間"],"Time until first merge request":["第一個合併請求被建立前的時間"],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有送交和合併的總測試時間"],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關資料,請向管理員申請權限。"],"We don't have enough data to show this stage.":["因該階段的資料不足而無法顯示相關資訊"],"You need permission.":["您需要相關的權限。"],"day":["天"]}}}; \ No newline at end of file
+var locales = locales || {}; locales['zh_TW'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Taiwan) (https://www.transifex.com/gitlab-zh/teams/75177/zh_TW/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_TW","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_TW","domain":"app","plural_forms":"nplurals=1; plural=0;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"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}":[""],"Branches":[""],"ByAuthor|by":["作者:"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["送交"],"CommitMessage|Add %{file_name}":["送交"],"Commits":["送交"],"Commits|History":["送交"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["相關的合併請求"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了你的專案從想法到產品實現,各階段所需的時間。"],"CycleAnalyticsStage|Code":["程式開發"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["上線"],"CycleAnalyticsStage|Review":["複閱"],"CycleAnalyticsStage|Staging":["預備"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["從議題建立至線上部署"],"From merge request merge until deploy to production":["從請求被合併後至線上部署"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["新議題"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["新議題"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["無法使用"],"Not enough data":["資料不足"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["專案生命週期"],"ProjectNetworkGraph|Graph":[""],"Read more":["了解更多"],"Readme":["了解更多"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["相關的送交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的請求"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["顯示 %d 個事件"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"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.":["程式開發階段顯示從第一次送交到建立合併請求的時間。建立第一個合併請求後,資料將自動填入。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"The fork relationship has been removed.":[""],"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.":["議題階段顯示從議題建立到設置里程碑、或將該議題加至議題看板的時間。建立第一個議題後,資料將自動填入。"],"The phase of the development lifecycle.":["專案開發生命週期的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段顯示從議題添加到日程後至推送第一個送交的時間。當第一次推送送交後,資料將自動填入。"],"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.":["上線階段顯示從建立一個議題到部署程式至線上的總時間。當完成從想法到產品實現的循環後,資料將自動填入。"],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["複閱階段顯示從合併請求建立後至被合併的時間。當建立第一個合併請求後,資料將自動填入。"],"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.":["預備階段顯示從合併請求被合併後至部署上線的時間。當第一次部署上線後,資料將自動填入。"],"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.":["測試階段顯示相關合併請求的流水線所花的時間。當第一個流水線運作完畢後,資料將自動填入。"],"The time taken by each data entry gathered by that stage.":["每筆該階段相關資料所花的時間。"],"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.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["議題等待開始實作的時間"],"Time between merge request creation and merge/close":["合併請求被合併或是關閉的時間"],"Time until first merge request":["第一個合併請求被建立前的時間"],"Timeago|%s days ago":["天"],"Timeago|%s days remaining":["天"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["天"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["天"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["天"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["天"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有送交和合併的總測試時間"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關資料,請向管理員申請權限。"],"We don't have enough data to show this stage.":["因該階段的資料不足而無法顯示相關資訊"],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["您需要相關的權限。"],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["天"],"notification emails":[""]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/pipelines/pipelines.js b/app/assets/javascripts/pipelines/pipelines.js
index 9f247af1dec..23b967b4b32 100644
--- a/app/assets/javascripts/pipelines/pipelines.js
+++ b/app/assets/javascripts/pipelines/pipelines.js
@@ -284,9 +284,7 @@ export default {
<table-pagination
v-if="shouldRenderPagination"
- :pagenum="pagenum"
:change="change"
- :count="state.count.all"
:pageInfo="state.pageInfo"
/>
</div>
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 75907c35b7e..19166757e64 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -1,4 +1,7 @@
.awards {
+ display: flex;
+ flex-wrap: wrap;
+
.emoji-icon {
width: 20px;
height: 20px;
@@ -100,7 +103,6 @@
.award-menu-holder {
display: inline-block;
- position: absolute;
.tooltip {
white-space: nowrap;
@@ -108,9 +110,11 @@
}
.award-control {
- margin: 0 5px 6px 0;
+ margin: 4px 8px 4px 0;
outline: 0;
position: relative;
+ display: block;
+ float: left;
&.disabled {
cursor: default;
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index 49163653548..38727e15c6f 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -264,3 +264,103 @@ ul.controls {
ul.indent-list {
padding: 10px 0 0 30px;
}
+
+
+// Specific styles for tree list
+.group-list-tree {
+ .folder-toggle-wrap {
+ float: left;
+ line-height: $list-text-height;
+ font-size: 0;
+
+ span {
+ font-size: $gl-font-size;
+ }
+ }
+
+ .folder-caret,
+ .folder-icon {
+ display: inline-block;
+ }
+
+ .folder-caret {
+ width: 15px;
+ }
+
+ .folder-icon {
+ width: 20px;
+ }
+
+ > .group-row:not(.has-subgroups) {
+ .folder-caret .fa {
+ opacity: 0;
+ }
+ }
+
+ .content-list li:last-child {
+ padding-bottom: 0;
+ }
+
+ .group-list-tree {
+ margin-bottom: 0;
+ margin-left: 30px;
+ position: relative;
+
+ &::before {
+ content: '';
+ display: block;
+ width: 0;
+ position: absolute;
+ top: 5px;
+ bottom: 0;
+ left: -16px;
+ border-left: 2px solid $border-white-normal;
+ }
+
+ .group-row {
+ position: relative;
+
+ &::before {
+ content: "";
+ display: block;
+ width: 10px;
+ height: 0;
+ border-top: 2px solid $border-white-normal;
+ position: absolute;
+ top: 30px;
+ left: -16px;
+ }
+
+ &:last-child::before {
+ background: $white-light;
+ height: auto;
+ top: 30px;
+ bottom: 0;
+ }
+ }
+ }
+
+ .group-row {
+ padding: 0;
+ border: none;
+ }
+
+ .group-row-contents {
+ padding: 10px 10px 8px;
+ border-top: solid 1px transparent;
+ border-bottom: solid 1px $white-normal;
+
+ &:hover {
+ border-color: $row-hover-border;
+ background-color: $row-hover;
+ cursor: pointer;
+ }
+ }
+}
+
+.js-groups-list-holder {
+ .groups-list-loading {
+ font-size: 34px;
+ text-align: center;
+ }
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index a321941e0c9..b3f310ff67d 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -58,7 +58,7 @@
}
.emoji-block {
- padding: 10px 0 4px;
+ padding: 10px 0;
}
}
@@ -756,7 +756,6 @@
position: -webkit-sticky;
top: 60px;
z-index: 200;
- @include transition(all);
}
}
}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 702e7662527..f923a1104a9 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -249,14 +249,19 @@ ul.related-merge-requests > li {
}
@media (min-width: $screen-sm-min) {
- .new-branch-col {
- padding-top: 0;
- text-align: right;
- }
+ .emoji-block .row {
+ display: flex;
- .create-mr-dropdown-wrap {
- .btn-group:not(.hide) {
- display: inline-block;
+ .new-branch-col {
+ padding-top: 0;
+ text-align: right;
+ align-self: center;
+ }
+
+ .create-mr-dropdown-wrap {
+ .btn-group:not(.hide) {
+ display: inline-block;
+ }
}
}
}
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
index 971d54e7472..4be0e133b69 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -3,6 +3,41 @@
border-bottom: 1px solid $border-color;
}
+.project-member-tabs {
+ background: $gray-light;
+ border: 1px solid $border-color;
+
+ li {
+ width: 50%;
+
+ &.active {
+ background: $white-light;
+ }
+
+ &:first-child {
+ border-right: 1px solid $border-color;
+ }
+
+ a {
+ width: 100%;
+ text-align: center;
+ }
+ }
+}
+
+.users-project-form {
+ .btn-create {
+ margin-right: 10px;
+ }
+}
+
+.project-member-tab-content {
+ padding: $gl-padding;
+ border: 1px solid $border-color;
+ border-top: 0;
+ margin-bottom: $gl-padding;
+}
+
.member {
.list-item-name {
@media (min-width: $screen-sm-min) {
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index cefb9b4e766..8d07780f6c2 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -52,9 +52,14 @@ module MembershipActions
"You left the \"#{membershipable.human_name}\" #{source_type}."
end
- redirect_path = member.request? ? member.source : [:dashboard, membershipable.class.to_s.tableize]
+ respond_to do |format|
+ format.html do
+ redirect_path = member.request? ? member.source : [:dashboard, membershipable.class.to_s.tableize]
+ redirect_to redirect_path, notice: notice
+ end
- redirect_to redirect_path, notice: notice
+ format.json { render json: { notice: notice } }
+ end
end
protected
diff --git a/app/controllers/dashboard/groups_controller.rb b/app/controllers/dashboard/groups_controller.rb
index d03265e9f20..742157d113d 100644
--- a/app/controllers/dashboard/groups_controller.rb
+++ b/app/controllers/dashboard/groups_controller.rb
@@ -1,16 +1,30 @@
class Dashboard::GroupsController < Dashboard::ApplicationController
def index
- @group_members = current_user.group_members.includes(source: :route).joins(:group)
- @group_members = @group_members.merge(Group.search(params[:filter_groups])) if params[:filter_groups].present?
- @group_members = @group_members.merge(Group.sort(@sort = params[:sort]))
- @group_members = @group_members.page(params[:page])
+ @groups =
+ if params[:parent_id] && Group.supports_nested_groups?
+ parent = Group.find_by(id: params[:parent_id])
+
+ if can?(current_user, :read_group, parent)
+ GroupsFinder.new(current_user, parent: parent).execute
+ else
+ Group.none
+ end
+ else
+ current_user.groups
+ end
+
+ @groups = @groups.search(params[:filter_groups]) if params[:filter_groups].present?
+ @groups = @groups.includes(:route)
+ @groups = @groups.sort(@sort = params[:sort])
+ @groups = @groups.page(params[:page])
respond_to do |format|
format.html
format.json do
- render json: {
- html: view_to_html_string("dashboard/groups/_groups", locals: { group_members: @group_members })
- }
+ render json: GroupSerializer
+ .new(current_user: @current_user)
+ .with_pagination(request, response)
+ .represent(@groups)
end
end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 7025c7a1de6..d8d14ea1fed 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -55,7 +55,7 @@ class Projects::BlobController < Projects::ApplicationController
def edit
if can_collaborate_with_project?
- blob.load_all_data!(@repository)
+ blob.load_all_data!
else
redirect_to action: 'show'
end
@@ -74,7 +74,7 @@ class Projects::BlobController < Projects::ApplicationController
def preview
@content = params[:content]
- @blob.load_all_data!(@repository)
+ @blob.load_all_data!
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
@@ -93,9 +93,11 @@ class Projects::BlobController < Projects::ApplicationController
def diff
apply_diff_view_cookie!
- @form = UnfoldForm.new(params)
- @lines = Gitlab::Highlight.highlight_lines(repository, @ref, @path)
- @lines = @lines[@form.since - 1..@form.to - 1]
+ @blob.load_all_data!
+ @lines = Gitlab::Highlight.highlight(@blob.path, @blob.data, repository: @repository).lines
+
+ @form = UnfoldForm.new(params)
+ @lines = @lines[@form.since - 1..@form.to - 1].map(&:html_safe)
if @form.bottom?
@match_line = ''
@@ -111,7 +113,7 @@ class Projects::BlobController < Projects::ApplicationController
private
def blob
- @blob ||= Blob.decorate(@repository.blob_at(@commit.id, @path), @project)
+ @blob ||= @repository.blob_at(@commit.id, @path)
if @blob
@blob
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index ac151839f61..1beac202efe 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -8,7 +8,7 @@ class Projects::LabelsController < Projects::ApplicationController
before_action :authorize_admin_labels!, only: [:new, :create, :edit, :update,
:generate, :destroy, :remove_priority,
:set_priorities]
- before_action :authorize_admin_group!, only: [:promote]
+ before_action :authorize_admin_group_labels!, only: [:promote]
respond_to :js, :html
@@ -161,7 +161,7 @@ class Projects::LabelsController < Projects::ApplicationController
return render_404 unless can?(current_user, :admin_label, @project)
end
- def authorize_admin_group!
- return render_404 unless can?(current_user, :admin_group, @project.group)
+ def authorize_admin_group_labels!
+ return render_404 unless can?(current_user, :admin_label, @project.group)
end
end
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index 2662a146968..ef4f083b98f 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -43,7 +43,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
if schedule.update(owner: current_user)
redirect_to pipeline_schedules_path(@project)
else
- redirect_to pipeline_schedules_path(@project), alert: "Failed to change the owner"
+ redirect_to pipeline_schedules_path(@project), alert: _("Failed to change the owner")
end
end
@@ -53,7 +53,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
else
redirect_to pipeline_schedules_path(@project),
status: 302,
- alert: "Failed to remove the pipeline schedule"
+ alert: _("Failed to remove the pipeline schedule")
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index a6014088e92..c003b01e226 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -8,7 +8,7 @@ module GroupsHelper
group = Group.find_by_full_path(group)
end
- group.try(:avatar_url) || image_path('no_group_avatar.png')
+ group.try(:avatar_url) || ActionController::Base.helpers.image_path('no_group_avatar.png')
end
def group_title(group, name = nil, url = nil)
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 17bfd07e00f..88dfe78c90c 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -13,7 +13,7 @@ module NavHelper
else
"page-gutter right-sidebar-expanded"
end
- elsif current_path?('builds#show')
+ elsif current_path?('jobs#show')
"page-gutter build-sidebar right-sidebar-expanded"
elsif current_path?('wikis#show') ||
current_path?('wikis#edit') ||
diff --git a/app/models/blob.rb b/app/models/blob.rb
index 6a42a12891c..3869e79ba75 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -94,6 +94,10 @@ class Blob < SimpleDelegator
end
end
+ def load_all_data!
+ super(project.repository) if project
+ end
+
def no_highlighting?
raw_size && raw_size > MAXIMUM_TEXT_HIGHLIGHT_SIZE
end
@@ -151,6 +155,10 @@ class Blob < SimpleDelegator
@extension ||= extname.downcase.delete('.')
end
+ def file_type
+ Gitlab::FileDetector.type_of(path)
+ end
+
def video?
UploaderHelper::VIDEO_EXT.include?(extension)
end
@@ -176,7 +184,7 @@ class Blob < SimpleDelegator
end
def rendered_as_text?(ignore_errors: true)
- simple_viewer.text? && (ignore_errors || simple_viewer.render_error.nil?)
+ simple_viewer.is_a?(BlobViewer::Text) && (ignore_errors || simple_viewer.render_error.nil?)
end
def show_viewer_switcher?
diff --git a/app/models/blob_viewer/base.rb b/app/models/blob_viewer/base.rb
index e6119d25fab..d2aa33d994e 100644
--- a/app/models/blob_viewer/base.rb
+++ b/app/models/blob_viewer/base.rb
@@ -52,7 +52,7 @@ module BlobViewer
def self.can_render?(blob, verify_binary: true)
return false if verify_binary && binary? != blob.binary?
return true if extensions&.include?(blob.extension)
- return true if file_types&.include?(Gitlab::FileDetector.type_of(blob.path))
+ return true if file_types&.include?(blob.file_type)
false
end
diff --git a/app/models/blob_viewer/empty.rb b/app/models/blob_viewer/empty.rb
index d9d128eb273..2380578ed72 100644
--- a/app/models/blob_viewer/empty.rb
+++ b/app/models/blob_viewer/empty.rb
@@ -4,6 +4,5 @@ module BlobViewer
include ServerSide
self.partial_name = 'empty'
- self.binary = true
end
end
diff --git a/app/models/blob_viewer/server_side.rb b/app/models/blob_viewer/server_side.rb
index 05a3dd7d913..e6bcacf7f70 100644
--- a/app/models/blob_viewer/server_side.rb
+++ b/app/models/blob_viewer/server_side.rb
@@ -9,9 +9,7 @@ module BlobViewer
end
def prepare!
- if blob.project
- blob.load_all_data!(blob.project.repository)
- end
+ blob.load_all_data!
end
def render_error
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 1a766c9f6d0..20206d57c4c 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -114,16 +114,16 @@ class Commit
#
# Usually, the commit title is the first line of the commit message.
# In case this first line is longer than 100 characters, it is cut off
- # after 80 characters and ellipses (`&hellp;`) are appended.
+ # after 80 characters + `...`
def title
- full_title.length > 100 ? full_title[0..79] << "…" : full_title
+ return full_title if full_title.length < 100
+
+ full_title.truncate(81, separator: ' ', omission: '…')
end
# Returns the full commits title
def full_title
- return @full_title if @full_title
-
- @full_title =
+ @full_title ||=
if safe_message.blank?
no_commit_message
else
@@ -131,19 +131,14 @@ class Commit
end
end
- # Returns the commits description
- #
- # cut off, ellipses (`&hellp;`) are prepended to the commit message.
+ # Returns full commit message if title is truncated (greater than 99 characters)
+ # otherwise returns commit message without first line
def description
- title_end = safe_message.index("\n")
- @description ||=
- if (!title_end && safe_message.length > 100) || (title_end && title_end > 100)
- "…" << safe_message[80..-1]
- else
- safe_message.split("\n", 2)[1].try(:chomp)
- end
- end
+ return safe_message if full_title.length >= 100
+ safe_message.split("\n", 2)[1].try(:chomp)
+ end
+
def description?
description.present?
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 0caf7387450..4c394646787 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -63,16 +63,6 @@ class Project < ActiveRecord::Base
# update visibility_level of forks
after_update :update_forks_visibility_level
- def update_forks_visibility_level
- return unless visibility_level < visibility_level_was
-
- forks.each do |forked_project|
- if forked_project.visibility_level > visibility_level
- forked_project.visibility_level = visibility_level
- forked_project.save!
- end
- end
- end
after_validation :check_pending_delete
@@ -165,7 +155,7 @@ class Project < ActiveRecord::Base
has_many :todos, dependent: :destroy
has_many :notification_settings, dependent: :destroy, as: :source
- has_one :import_data, dependent: :delete, class_name: "ProjectImportData"
+ has_one :import_data, dependent: :delete, class_name: 'ProjectImportData'
has_one :project_feature, dependent: :destroy
has_one :statistics, class_name: 'ProjectStatistics', dependent: :delete
has_many :container_repositories, dependent: :destroy
@@ -488,7 +478,11 @@ class Project < ActiveRecord::Base
ProjectCacheWorker.perform_async(self.id)
end
- self.import_data&.destroy
+ remove_import_data
+ end
+
+ def remove_import_data
+ import_data&.destroy
end
def import_url=(value)
@@ -1060,6 +1054,17 @@ class Project < ActiveRecord::Base
!!repository.exists?
end
+ def update_forks_visibility_level
+ return unless visibility_level < visibility_level_was
+
+ forks.each do |forked_project|
+ if forked_project.visibility_level > visibility_level
+ forked_project.visibility_level = visibility_level
+ forked_project.save!
+ end
+ end
+ end
+
def create_wiki
ProjectWiki.new(self, self.owner).wiki
true
@@ -1068,6 +1073,10 @@ class Project < ActiveRecord::Base
false
end
+ def wiki
+ @wiki ||= ProjectWiki.new(self, self.owner)
+ end
+
def jira_tracker_active?
jira_tracker? && jira_service.active
end
@@ -1190,10 +1199,6 @@ class Project < ActiveRecord::Base
end
end
- def wiki
- @wiki ||= ProjectWiki.new(self, self.owner)
- end
-
def running_or_pending_build_count(force: false)
Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do
builds.running_or_pending.count(:all)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 00a0b407512..7460515fea8 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1104,7 +1104,7 @@ class Repository
blob = blob_at(sha, path)
return unless blob
- blob.load_all_data!(self)
+ blob.load_all_data!
blob.data
end
diff --git a/app/serializers/group_entity.rb b/app/serializers/group_entity.rb
new file mode 100644
index 00000000000..4f506f7e745
--- /dev/null
+++ b/app/serializers/group_entity.rb
@@ -0,0 +1,46 @@
+class GroupEntity < Grape::Entity
+ include ActionView::Helpers::NumberHelper
+ include RequestAwareEntity
+ include MembersHelper
+ include GroupsHelper
+
+ expose :id, :name, :path, :description, :visibility
+ expose :web_url
+ expose :full_name, :full_path
+ expose :parent_id
+ expose :created_at, :updated_at
+
+ expose :permissions do
+ expose :human_group_access do |group, options|
+ group.group_members.find_by(user_id: request.current_user)&.human_access
+ end
+ end
+
+ expose :edit_path do |group|
+ edit_group_path(group)
+ end
+
+ expose :leave_path do |group|
+ leave_group_group_members_path(group)
+ end
+
+ expose :can_edit do |group|
+ can?(request.current_user, :admin_group, group)
+ end
+
+ expose :has_subgroups do |group|
+ GroupsFinder.new(request.current_user, parent: group).execute.any?
+ end
+
+ expose :number_projects_with_delimiter do |group|
+ number_with_delimiter(GroupProjectsFinder.new(group: group, current_user: request.current_user).execute.count)
+ end
+
+ expose :number_users_with_delimiter do |group|
+ number_with_delimiter(group.users.count)
+ end
+
+ expose :avatar_url do |group|
+ group_icon(group)
+ end
+end
diff --git a/app/serializers/group_serializer.rb b/app/serializers/group_serializer.rb
new file mode 100644
index 00000000000..26e8566828b
--- /dev/null
+++ b/app/serializers/group_serializer.rb
@@ -0,0 +1,19 @@
+class GroupSerializer < BaseSerializer
+ entity GroupEntity
+
+ def with_pagination(request, response)
+ tap { @paginator = Gitlab::Serializer::Pagination.new(request, response) }
+ end
+
+ def paginated?
+ @paginator.present?
+ end
+
+ def represent(resource, opts = {})
+ if paginated?
+ super(@paginator.paginate(resource), opts)
+ else
+ super(resource, opts)
+ end
+ end
+end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index bffec216819..769749c9925 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -57,6 +57,8 @@ module Ci
cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
+ pipeline_created_counter.increment(source: source)
+
pipeline.tap(&:process!)
end
@@ -131,5 +133,9 @@ module Ci
pipeline.drop if save
pipeline
end
+
+ def pipeline_created_counter
+ @pipeline_created_counter ||= Gitlab::Metrics.counter(:pipelines_created_count, "Pipelines created count")
+ end
end
end
diff --git a/app/uploaders/gitlab_uploader.rb b/app/uploaders/gitlab_uploader.rb
index a50169a5076..0048e07e1f2 100644
--- a/app/uploaders/gitlab_uploader.rb
+++ b/app/uploaders/gitlab_uploader.rb
@@ -19,10 +19,12 @@ class GitlabUploader < CarrierWave::Uploader::Base
File.join(root_dir, 'system')
end
- def file_storage?
- storage.is_a?(CarrierWave::Storage::File)
+ def self.file_storage?
+ self.storage == CarrierWave::Storage::File
end
+ delegate :base_dir, :file_storage?, to: :class
+
def file_cache_storage?
cache_storage.is_a?(CarrierWave::Storage::File)
end
diff --git a/app/views/dashboard/groups/_groups.html.haml b/app/views/dashboard/groups/_groups.html.haml
index 6c3bf1a2b3b..168e6272d8e 100644
--- a/app/views/dashboard/groups/_groups.html.haml
+++ b/app/views/dashboard/groups/_groups.html.haml
@@ -1,6 +1,9 @@
.js-groups-list-holder
- %ul.content-list
- - @group_members.each do |group_member|
- = render 'shared/groups/group', group: group_member.group, group_member: group_member
-
- = paginate @group_members, theme: 'gitlab'
+ #dashboard-group-app{ data: { endpoint: dashboard_groups_path(format: :json), path: dashboard_groups_path } }
+ .groups-list-loading
+ = icon('spinner spin', 'v-show' => 'isLoading')
+ %template{ 'v-if' => '!isLoading && isEmpty' }
+ %div{ 'v-cloak' => true }
+ = render 'empty_state'
+ %template{ 'v-else-if' => '!isLoading && !isEmpty' }
+ %groups-component{ ':groups' => 'state.groups', ':page-info' => 'state.pageInfo' }
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
index 73ab2c95ff9..f9b45a539a1 100644
--- a/app/views/dashboard/groups/index.html.haml
+++ b/app/views/dashboard/groups/index.html.haml
@@ -2,7 +2,10 @@
- header_title "Groups", dashboard_groups_path
= render 'dashboard/groups_head'
-- if @group_members.empty?
+= webpack_bundle_tag 'common_vue'
+= webpack_bundle_tag 'groups'
+
+- if @groups.empty?
= render 'empty_state'
- else
= render 'groups'
diff --git a/app/views/projects/diffs/_content.html.haml b/app/views/projects/diffs/_content.html.haml
index 59844bc00cd..ec1c434a4b8 100644
--- a/app/views/projects/diffs/_content.html.haml
+++ b/app/views/projects/diffs/_content.html.haml
@@ -6,7 +6,7 @@
- elsif blob.truncated?
.nothing-here-block The file could not be displayed because it is too large.
- elsif blob.readable_text?
- - if !diff_file.repository.diffable?(blob)
+ - if !diff_file.diffable?
.nothing-here-block This diff was suppressed by a .gitattributes entry.
- elsif diff_file.collapsed?
- url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier))
diff --git a/app/views/projects/diffs/viewers/_text.html.haml b/app/views/projects/diffs/viewers/_text.html.haml
index e4b89671724..120d3540223 100644
--- a/app/views/projects/diffs/viewers/_text.html.haml
+++ b/app/views/projects/diffs/viewers/_text.html.haml
@@ -1,5 +1,5 @@
- blob = diff_file.blob
-- blob.load_all_data!(diff_file.repository)
+- blob.load_all_data!
- total_lines = blob.lines.size
- total_lines -= 1 if total_lines > 0 && blob.lines.last.blank?
- if diff_view == :parallel
diff --git a/app/views/projects/group_links/_index.html.haml b/app/views/projects/group_links/_index.html.haml
deleted file mode 100644
index debb0214d06..00000000000
--- a/app/views/projects/group_links/_index.html.haml
+++ /dev/null
@@ -1,53 +0,0 @@
-- page_title "Groups"
-.row.prepend-top-default
- .col-lg-3.settings-sidebar
- %h4.prepend-top-0
- Share project with other groups
- %p
- Projects can be stored in only one group at once. However you can share a project with other groups here.
- .col-lg-9
- = form_tag namespace_project_group_links_path(@project.namespace, @project), class: 'js-requires-input', method: :post do
- .form-group
- = label_tag :link_group_id, "Select a group to share with", class: "label-light"
- = groups_select_tag(:link_group_id, data: { skip_groups: @skip_groups }, required: true)
- .form-group
- = label_tag :link_group_access, "Max access level", class: "label-light"
- .select-wrapper
- = select_tag :link_group_access, options_for_select(ProjectGroupLink.access_options, ProjectGroupLink.default_access), class: "form-control select-control"
- = icon('caret-down')
- .form-group
- = label_tag :expires_at, 'Access expiration date', class: 'label-light'
- .clearable-input
- = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date-groups', placeholder: 'Select access expiration date', id: 'expires_at_groups'
- %i.clear-icon.js-clear-input
- .help-block
- On this date, all members in the group will automatically lose access to this project.
- = submit_tag "Share", class: "btn btn-create"
- .col-lg-9.col-lg-offset-3
- %hr
- .col-lg-9.col-lg-offset-3.append-bottom-default.enabled-groups
- %h5.prepend-top-0
- Groups you share with (#{@group_links.size})
- - if @group_links.present?
- %ul.well-list
- - @group_links.each do |group_link|
- - group = group_link.group
- %li
- .pull-left.append-right-10.hidden-xs
- = icon("folder-open-o", class: "settings-list-icon")
- .pull-left
- = link_to group do
- = group.full_name
- %br
- up to #{group_link.human_access}
- - if group_link.expires?
- ·
- %span{ class: ('text-warning' if group_link.expires_soon?) }
- expires in #{distance_of_time_in_words_to_now(group_link.expires_at)}
- .pull-right
- = link_to namespace_project_group_link_path(@project.namespace, @project, group_link), method: :delete, class: "btn btn-transparent" do
- %span.sr-only disable sharing
- = icon("trash")
- - else
- .settings-message.text-center
- There are no groups with access to your project, add one in the form above
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index bbed10039af..25ae4e0e18f 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -6,28 +6,28 @@
= form_errors(@schedule)
.form-group
.col-md-9
- = f.label :description, 'Description', class: 'label-light'
- = f.text_field :description, class: 'form-control', required: true, autofocus: true, placeholder: 'Provide a short description for this pipeline'
+ = f.label :description, _('Description'), class: 'label-light'
+ = f.text_field :description, class: 'form-control', required: true, autofocus: true, placeholder: _('PipelineSchedules|Provide a short description for this pipeline')
.form-group
.col-md-9
- = f.label :cron, 'Interval Pattern', class: 'label-light'
+ = f.label :cron, _('Interval Pattern'), class: 'label-light'
#interval-pattern-input{ data: { initial_interval: @schedule.cron } }
.form-group
.col-md-9
- = f.label :cron_timezone, 'Cron Timezone', class: 'label-light'
- = dropdown_tag("Select a timezone", options: { toggle_class: 'btn js-timezone-dropdown', title: "Select a timezone", filter: true, placeholder: "Filter", data: { data: timezone_data } } )
+ = f.label :cron_timezone, _('Cron Timezone'), class: 'label-light'
+ = dropdown_tag(_("Select a timezone"), options: { toggle_class: 'btn js-timezone-dropdown', title: _("Select a timezone"), filter: true, placeholder: _("Filter"), data: { data: timezone_data } } )
= f.text_field :cron_timezone, value: @schedule.cron_timezone, id: 'schedule_cron_timezone', class: 'hidden', name: 'schedule[cron_timezone]', required: true
.form-group
.col-md-9
- = f.label :ref, 'Target Branch', class: 'label-light'
- = dropdown_tag("Select target branch", options: { toggle_class: 'btn js-target-branch-dropdown git-revision-dropdown-toggle', dropdown_class: 'git-revision-dropdown', title: "Select target branch", filter: true, placeholder: "Filter", data: { data: @project.repository.branch_names, default_branch: @project.default_branch } } )
+ = f.label :ref, _('Target Branch'), class: 'label-light'
+ = dropdown_tag(_("Select target branch"), options: { toggle_class: 'btn js-target-branch-dropdown git-revision-dropdown-toggle', dropdown_class: 'git-revision-dropdown', title: _("Select target branch"), filter: true, placeholder: _("Filter"), data: { data: @project.repository.branch_names, default_branch: @project.default_branch } } )
= f.text_field :ref, value: @schedule.ref, id: 'schedule_ref', class: 'hidden', name: 'schedule[ref]', required: true
.form-group
.col-md-9
- = f.label :active, 'Activated', class: 'label-light'
+ = f.label :active, _('PipelineSchedules|Activated'), class: 'label-light'
%div
= f.check_box :active, required: false, value: @schedule.active?
Active
.footer-block.row-content-block
- = f.submit 'Save pipeline schedule', class: 'btn btn-create', tabindex: 3
- = link_to 'Cancel', pipeline_schedules_path(@project), class: 'btn btn-cancel'
+ = f.submit _('Save pipeline schedule'), class: 'btn btn-create', tabindex: 3
+ = link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn btn-cancel'
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index 7bde839e26f..2d3344a4aaf 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -13,12 +13,12 @@
= ci_icon_for_status(pipeline_schedule.last_pipeline.status)
%span ##{pipeline_schedule.last_pipeline.id}
- else
- None
+ = _("PipelineSchedules|None")
%td.next-run-cell
- if pipeline_schedule.active?
= time_ago_with_tooltip(pipeline_schedule.real_next_run)
- else
- Inactive
+ = _("PipelineSchedules|Inactive")
%td
- if pipeline_schedule.owner
= image_tag avatar_icon(pipeline_schedule.owner, 20), class: "avatar s20"
@@ -27,11 +27,11 @@
%td
.pull-right.btn-group
- if can?(current_user, :update_pipeline_schedule, @project) && !pipeline_schedule.owned_by?(current_user)
- = link_to take_ownership_pipeline_schedule_path(pipeline_schedule), method: :post, title: 'Take Ownership', class: 'btn' do
- Take ownership
+ = link_to take_ownership_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('PipelineSchedules|Take ownership'), class: 'btn' do
+ = s_('PipelineSchedules|Take ownership')
- if can?(current_user, :update_pipeline_schedule, pipeline_schedule)
- = link_to edit_pipeline_schedule_path(pipeline_schedule), title: 'Edit', class: 'btn' do
+ = link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn' do
= icon('pencil')
- if can?(current_user, :admin_pipeline_schedule, pipeline_schedule)
- = link_to pipeline_schedule_path(pipeline_schedule), title: 'Delete', method: :delete, class: 'btn btn-remove', data: { confirm: "Are you sure you want to cancel this pipeline?" } do
+ = link_to pipeline_schedule_path(pipeline_schedule), title: _('Delete'), method: :delete, class: 'btn btn-remove', data: { confirm: _("Are you sure you want to delete this pipeline schedule?") } do
= icon('trash')
diff --git a/app/views/projects/pipeline_schedules/_table.html.haml b/app/views/projects/pipeline_schedules/_table.html.haml
index 25c7604eb24..d0c7ea77263 100644
--- a/app/views/projects/pipeline_schedules/_table.html.haml
+++ b/app/views/projects/pipeline_schedules/_table.html.haml
@@ -2,11 +2,11 @@
%table.table.ci-table
%thead
%tr
- %th Description
- %th Target
- %th Last Pipeline
- %th Next Run
- %th Owner
+ %th= _("Description")
+ %th= s_("PipelineSchedules|Target")
+ %th= _("Last Pipeline")
+ %th= s_("PipelineSchedules|Next Run")
+ %th= _("Owner")
%th
= render partial: "pipeline_schedule", collection: @schedules
diff --git a/app/views/projects/pipeline_schedules/_tabs.html.haml b/app/views/projects/pipeline_schedules/_tabs.html.haml
index 2a1fb16876a..7fcb624a9dd 100644
--- a/app/views/projects/pipeline_schedules/_tabs.html.haml
+++ b/app/views/projects/pipeline_schedules/_tabs.html.haml
@@ -1,18 +1,18 @@
%ul.nav-links
%li{ class: active_when(scope.nil?) }>
= link_to schedule_path_proc.call(nil) do
- All
+ = s_("PipelineSchedules|All")
%span.badge.js-totalbuilds-count
= number_with_delimiter(all_schedules.count(:id))
%li{ class: active_when(scope == 'active') }>
= link_to schedule_path_proc.call('active') do
- Active
+ = s_("PipelineSchedules|Active")
%span.badge
= number_with_delimiter(all_schedules.active.count(:id))
%li{ class: active_when(scope == 'inactive') }>
= link_to schedule_path_proc.call('inactive') do
- Inactive
+ = s_("PipelineSchedules|Inactive")
%span.badge
= number_with_delimiter(all_schedules.inactive.count(:id))
diff --git a/app/views/projects/pipeline_schedules/edit.html.haml b/app/views/projects/pipeline_schedules/edit.html.haml
index e16fe0b7a98..9b2a7b5821d 100644
--- a/app/views/projects/pipeline_schedules/edit.html.haml
+++ b/app/views/projects/pipeline_schedules/edit.html.haml
@@ -1,7 +1,7 @@
-- page_title "Edit", @schedule.description, "Pipeline Schedule"
+- page_title _("Edit"), @schedule.description, _("Pipeline Schedule")
%h3.page-title
- Edit Pipeline Schedule #{@schedule.id}
+ = _("Edit Pipeline Schedule %{id}") % { id: @schedule.id }
%hr
= render "form"
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index 6751efaaf2f..4a96ee652d2 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -3,7 +3,7 @@
= webpack_bundle_tag 'schedules_index'
- @no_container = true
-- page_title "Pipeline Schedules"
+- page_title _("Pipeline Schedules")
= render "projects/pipelines/head"
%div{ class: container_class }
@@ -21,4 +21,4 @@
= render partial: "table"
- else
.light-well
- .nothing-here-block No schedules
+ .nothing-here-block= _("No schedules")
diff --git a/app/views/projects/pipeline_schedules/new.html.haml b/app/views/projects/pipeline_schedules/new.html.haml
index b89e170ad3c..87390d4dd02 100644
--- a/app/views/projects/pipeline_schedules/new.html.haml
+++ b/app/views/projects/pipeline_schedules/new.html.haml
@@ -1,7 +1,7 @@
-- page_title "New Pipeline Schedule"
+- page_title _("New Pipeline Schedule")
%h3.page-title
- Schedule a new pipeline
+ = _("Schedule a new pipeline")
%hr
= render "form"
diff --git a/app/views/projects/project_members/_index.html.haml b/app/views/projects/project_members/_index.html.haml
index d080b6c83d4..cfae371e169 100644
--- a/app/views/projects/project_members/_index.html.haml
+++ b/app/views/projects/project_members/_index.html.haml
@@ -1,11 +1,12 @@
.row.prepend-top-default
.col-lg-3.settings-sidebar
%h4.prepend-top-0
- Members
+ Project members
- if can?(current_user, :admin_project_member, @project)
%p
- Add a new member to
+ You can add a new member to
%strong= @project.name
+ or share it with another group.
- else
%p
Members can be added by project
@@ -13,9 +14,20 @@
or
%i Owners
.col-lg-9
- .light.prepend-top-default
+ .light
- if can?(current_user, :admin_project_member, @project)
- = render "projects/project_members/new_project_member"
+ %ul.nav-links.project-member-tabs{ role: 'tablist' }
+ %li.active{ role: 'presentation' }
+ %a{ href: '#add-member-pane', id: 'add-member-tab', data: { toggle: 'tab' }, role: 'tab' } Add member
+ - if @project.allowed_to_share_with_group?
+ %li{ role: 'presentation' }
+ %a{ href: '#share-with-group-pane', id: 'share-with-group-tab', data: { toggle: 'tab' }, role: 'tab' } Share with group
+
+ .tab-content.project-member-tab-content
+ .tab-pane.active{ id: 'add-member-pane', role: 'tabpanel' }
+ = render 'projects/project_members/new_project_member', tab_title: 'Add member'
+ .tab-pane{ id: 'share-with-group-pane', role: 'tabpanel' }
+ = render 'projects/project_members/new_shared_group', tab_title: 'Share with group'
= render 'shared/members/requests', membership_source: @project, requesters: @requesters
.clearfix
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 2b1c23f7dda..247c4bdbe2d 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -1,18 +1,19 @@
-= form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'users-project-form' } do |f|
- .form-group
- = users_select_tag(:user_ids, multiple: true, class: "input-clamp", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
- .help-block.append-bottom-10
- Search for members by name, username, or email, or invite new ones using their email address.
- .form-group
- = select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "form-control project-access-select"
- .help-block.append-bottom-10
- = link_to "Read more", help_page_path("user/permissions"), class: "vlink"
- about role permissions
- .form-group
- .clearable-input
- = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
- %i.clear-icon.js-clear-input
- .help-block.append-bottom-10
- On this date, the member(s) will automatically lose access to this project.
- = f.submit "Add to project", class: "btn btn-create"
- = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default", title: "Import members from another project"
+.row
+ .col-sm-12
+ = form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'users-project-form' } do |f|
+ .form-group
+ = label_tag :user_ids, "Select members to invite", class: "label-light"
+ = users_select_tag(:user_ids, multiple: true, class: "input-clamp", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
+ .form-group
+ = label_tag :access_level, "Choose a role permission", class: "label-light"
+ = select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "form-control project-access-select"
+ .help-block.append-bottom-10
+ = link_to "Read more", help_page_path("user/permissions"), class: "vlink"
+ about role permissions
+ .form-group
+ .clearable-input
+ = label_tag :expires_at, 'Access expiration date', class: 'label-light'
+ = 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-create"
+ = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default", title: "Import members from another project"
diff --git a/app/views/projects/project_members/_new_shared_group.html.haml b/app/views/projects/project_members/_new_shared_group.html.haml
new file mode 100644
index 00000000000..b7cc8dd7062
--- /dev/null
+++ b/app/views/projects/project_members/_new_shared_group.html.haml
@@ -0,0 +1,20 @@
+.row
+ .col-sm-12
+ = form_tag namespace_project_group_links_path(@project.namespace, @project), class: 'js-requires-input', method: :post do
+ .form-group
+ = label_tag :link_group_id, "Select a group to share with", class: "label-light"
+ = groups_select_tag(:link_group_id, data: { skip_groups: @skip_groups }, class: "input-clamp", required: true)
+ .form-group
+ = label_tag :link_group_access, "Max access level", class: "label-light"
+ .select-wrapper
+ = select_tag :link_group_access, options_for_select(ProjectGroupLink.access_options, ProjectGroupLink.default_access), class: "form-control select-control"
+ = icon('caret-down')
+ .help-block.append-bottom-10
+ = link_to "Read more", help_page_path("user/permissions"), class: "vlink"
+ about role permissions
+ .form-group
+ = label_tag :expires_at, 'Access expiration date', class: 'label-light'
+ .clearable-input
+ = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date-groups', placeholder: 'Expiration date', id: 'expires_at_groups'
+ %i.clear-icon.js-clear-input
+ = submit_tag "Share", class: "btn btn-create"
diff --git a/app/views/projects/settings/members/show.html.haml b/app/views/projects/settings/members/show.html.haml
index 20e1ad68244..343807b87cd 100644
--- a/app/views/projects/settings/members/show.html.haml
+++ b/app/views/projects/settings/members/show.html.haml
@@ -2,6 +2,3 @@
= render "projects/settings/head"
= render "projects/project_members/index"
-- if can?(current_user, :admin_project, @project)
- - if @project.allowed_to_share_with_group?
- = render "projects/group_links/index"
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index bd994cdad01..c185e9b73ee 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -64,7 +64,7 @@
%a.js-subscribe-button{ data: { url: toggle_subscription_group_label_path(label.group, label) } }
Group level
- - if label.is_a?(ProjectLabel) && label.project.group && can?(current_user, :admin_group, label.project.group)
+ - if label.is_a?(ProjectLabel) && label.project.group && can?(current_user, :admin_label, label.project.group)
= link_to promote_namespace_project_label_path(label.project.namespace, label.project, label), title: "Promote to Group Label", class: 'btn btn-transparent btn-action', data: {confirm: "Promoting this label will make this label available to all projects inside this group. Existing project labels with the same name will be merged. Are you sure?", toggle: "tooltip"}, method: :post do
%span.sr-only Promote to Group
= icon('level-up')
diff --git a/app/views/shared/groups/_dropdown.html.haml b/app/views/shared/groups/_dropdown.html.haml
index 37589b634fa..760370a6984 100644
--- a/app/views/shared/groups/_dropdown.html.haml
+++ b/app/views/shared/groups/_dropdown.html.haml
@@ -1,10 +1,10 @@
-.dropdown.inline
+.dropdown.inline.js-group-filter-dropdown-wrap
%button.dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
- %span.light
- - if @sort.present?
- = sort_options_hash[@sort]
- - else
- = sort_title_recently_created
+ %span.dropdown-label
+ - if @sort.present?
+ = sort_options_hash[@sort]
+ - else
+ = sort_title_recently_created
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-align-right
%li
diff --git a/changelogs/unreleased/12614-fix-long-message.yml b/changelogs/unreleased/12614-fix-long-message.yml
new file mode 100644
index 00000000000..94f8127c3c1
--- /dev/null
+++ b/changelogs/unreleased/12614-fix-long-message.yml
@@ -0,0 +1,4 @@
+---
+title: Fix long urls in the title of commit
+merge_request: 10938
+author: Alexander Randa
diff --git a/changelogs/unreleased/25426-group-dashboard-ui.yml b/changelogs/unreleased/25426-group-dashboard-ui.yml
new file mode 100644
index 00000000000..cc2bf62d07b
--- /dev/null
+++ b/changelogs/unreleased/25426-group-dashboard-ui.yml
@@ -0,0 +1,4 @@
+---
+title: Update Dashboard Groups UI with better support for subgroups
+merge_request:
+author:
diff --git a/changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml b/changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml
new file mode 100644
index 00000000000..9cf8d745f92
--- /dev/null
+++ b/changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml
@@ -0,0 +1,4 @@
+---
+title: Confirm Project forking behaviour via the API
+merge_request:
+author:
diff --git a/changelogs/unreleased/32720-emoji-spacing.yml b/changelogs/unreleased/32720-emoji-spacing.yml
new file mode 100644
index 00000000000..da3df0f9093
--- /dev/null
+++ b/changelogs/unreleased/32720-emoji-spacing.yml
@@ -0,0 +1,4 @@
+---
+title: Create equal padding for emoji
+merge_request:
+author:
diff --git a/changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml b/changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml
new file mode 100644
index 00000000000..a0e0458da16
--- /dev/null
+++ b/changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml
@@ -0,0 +1,4 @@
+---
+title: Add Portuguese Brazil of Cycle Analytics Page to I18N
+merge_request: 11920
+author:Huang Tao
diff --git a/changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml b/changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml
new file mode 100644
index 00000000000..71bd5505be7
--- /dev/null
+++ b/changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml
@@ -0,0 +1,4 @@
+---
+title: add bulgarian translation of cycle analytics page to I18N
+merge_request: 11958
+author: Lyubomir Vasilev
diff --git a/changelogs/unreleased/allow-reporters-to-promote-group-labels.yml b/changelogs/unreleased/allow-reporters-to-promote-group-labels.yml
new file mode 100644
index 00000000000..2364ce6d068
--- /dev/null
+++ b/changelogs/unreleased/allow-reporters-to-promote-group-labels.yml
@@ -0,0 +1,4 @@
+---
+title: Allow reporters to promote project labels to group labels
+merge_request:
+author:
diff --git a/changelogs/unreleased/artifacts-keyboard-shortcuts.yml b/changelogs/unreleased/artifacts-keyboard-shortcuts.yml
new file mode 100644
index 00000000000..69569504c4f
--- /dev/null
+++ b/changelogs/unreleased/artifacts-keyboard-shortcuts.yml
@@ -0,0 +1,4 @@
+---
+title: Enabled keyboard shortcuts on artifacts pages
+merge_request:
+author:
diff --git a/changelogs/unreleased/ce-31853-projects-shared-groups.yml b/changelogs/unreleased/ce-31853-projects-shared-groups.yml
new file mode 100644
index 00000000000..ffa3aed682d
--- /dev/null
+++ b/changelogs/unreleased/ce-31853-projects-shared-groups.yml
@@ -0,0 +1,4 @@
+---
+title: Remove duplication for sharing projects with groups in project settings
+merge_request:
+author:
diff --git a/changelogs/unreleased/zj-i18n-pipeline-schedules.yml b/changelogs/unreleased/zj-i18n-pipeline-schedules.yml
new file mode 100644
index 00000000000..51c82a16359
--- /dev/null
+++ b/changelogs/unreleased/zj-i18n-pipeline-schedules.yml
@@ -0,0 +1,4 @@
+---
+title: Allow translation of Pipeline Schedules
+merge_request:
+author:
diff --git a/changelogs/unreleased/zj-prom-pipeline-count.yml b/changelogs/unreleased/zj-prom-pipeline-count.yml
new file mode 100644
index 00000000000..191e4f2f949
--- /dev/null
+++ b/changelogs/unreleased/zj-prom-pipeline-count.yml
@@ -0,0 +1,4 @@
+---
+title: Add prometheus metrics on pipeline creation
+merge_request:
+author:
diff --git a/config/webpack.config.js b/config/webpack.config.js
index cbcf5ce996d..7501acb7633 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -40,6 +40,7 @@ var config = {
filtered_search: './filtered_search/filtered_search_bundle.js',
graphs: './graphs/graphs_bundle.js',
group: './group.js',
+ groups: './groups/index.js',
groups_list: './groups_list.js',
issue_show: './issue_show/index.js',
integrations: './integrations',
@@ -155,6 +156,7 @@ var config = {
'environments',
'environments_folder',
'filtered_search',
+ 'groups',
'issue_show',
'merge_conflicts',
'notebook_viewer',
diff --git a/db/schema.rb b/db/schema.rb
index 83172a92b49..b93630a410d 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,8 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170603200744) do
-
+ActiveRecord::Schema.define(version: 20170606202615) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
enable_extension "pg_trgm"
diff --git a/doc/api/README.md b/doc/api/README.md
index e1d4009dedc..2175b305e02 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -55,6 +55,15 @@ following locations:
- [V3 to V4](v3_to_v4.md)
- [Version](version.md)
+## Road to GraphQL
+
+API v4 will be the last REST API that we support. Going forward, we will start
+on moving to GraphQL and deprecate the use of controller-specific
+endpoints. GraphQL has a number of benefits:
+
+1. We avoid having to maintain two different APIs.
+2. Callers of the API can request only what they need.
+
### Internal CI API
The following documentation is for the [internal CI API](ci/README.md):
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 0debdcfae89..bf21aa0e179 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -415,6 +415,8 @@ Parameters:
Forks a project into the user namespace of the authenticated user or the one provided.
+The forking operation for a project is asynchronous and is completed in a background job. The request will return immediately. To determine whether the fork of the project has completed, query the `import_status` for the new project.
+
```
POST /projects/:id/fork
```
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index 1bd1ee93ac5..73aee3c3f56 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -1,124 +1,168 @@
# Runners
-In GitLab CI, Runners run your [yaml](../yaml/README.md).
-A Runner is an isolated (virtual) machine that picks up jobs
-through the coordinator API of GitLab CI.
+In GitLab CI, Runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md).
+They are isolated (virtual) machines that pick up jobs through the coordinator
+API of GitLab CI.
A Runner can be specific to a certain project or serve any project
in GitLab CI. A Runner that serves all projects is called a shared Runner.
-Ideally, GitLab Runner should not be installed on the same machine as GitLab.
+Ideally, the GitLab Runner should not be installed on the same machine as GitLab.
Read the [requirements documentation](../../install/requirements.md#gitlab-runner)
for more information.
-## Shared vs. Specific Runners
-
-A Runner that is specific only runs for the specified project. A shared Runner
-can run jobs for every project that has enabled the option **Allow shared Runners**.
-
-**Shared Runners** are useful for jobs that have similar requirements,
-between multiple projects. Rather than having multiple Runners idling for
-many projects, you can have a single or a small number of Runners that handle
-multiple projects. This makes it easier to maintain and update Runners.
-
-**Specific Runners** are useful for jobs that have special requirements or for
-projects with a specific demand. If a job has certain requirements, you can set
-up the specific Runner with this in mind, while not having to do this for all
-Runners. For example, if you want to deploy a certain project, you can setup
-a specific Runner to have the right credentials for this.
-
-Projects with high demand of CI activity can also benefit from using specific Runners.
-By having dedicated Runners you are guaranteed that the Runner is not being held
-up by another project's jobs.
+## Shared vs specific Runners
+
+After [installing the Runner][install], you can either register it as shared or
+specific. You can only register a shared Runner if you have admin access to
+the GitLab instance. The main differences between a shared and a specific Runner
+are:
+
+- **Shared Runners** are useful for jobs that have similar requirements,
+ between multiple projects. Rather than having multiple Runners idling for
+ many projects, you can have a single or a small number of Runners that handle
+ multiple projects. This makes it easier to maintain and update them.
+ Shared Runners process jobs using a [fair usage queue](#how-shared-runners-pick-jobs).
+ In contrast to specific Runners that use a FIFO queue, this prevents
+ cases where projects create hundreds of jobs which can lead to eating all
+ available shared Runners resources.
+- **Specific Runners** are useful for jobs that have special requirements or for
+ projects with a specific demand. If a job has certain requirements, you can set
+ up the specific Runner with this in mind, while not having to do this for all
+ Runners. For example, if you want to deploy a certain project, you can setup
+ a specific Runner to have the right credentials for this. The [usage of tags](#using-tags)
+ may be useful in this case. Specific Runners process jobs using a [FIFO] queue.
+
+A Runner that is specific only runs for the specified project(s). A shared Runner
+can run jobs for every project that has enabled the option **Allow shared Runners**
+under **Settings ➔ Pipelines**.
+
+Projects with high demand of CI activity can also benefit from using specific
+Runners. By having dedicated Runners you are guaranteed that the Runner is not
+being held up by another project's jobs.
You can set up a specific Runner to be used by multiple projects. The difference
with a shared Runner is that you have to enable each project explicitly for
the Runner to be able to run its jobs.
Specific Runners do not get shared with forked projects automatically.
-A fork does copy the CI settings (jobs, allow shared, etc) of the cloned repository.
-
-# Creating and Registering a Runner
-
-There are several ways to create a Runner. Only after creation, upon
-registration its status as Shared or Specific is determined.
-
-[See the documentation for](https://docs.gitlab.com/runner/install)
-the different methods of installing a Runner instance.
+A fork does copy the CI settings (jobs, allow shared, etc) of the cloned
+repository.
-After installing the Runner, you can either register it as `Shared` or as `Specific`.
-You can only register a Shared Runner if you have admin access to the GitLab instance.
+## Registering a shared Runner
-## Registering a Shared Runner
+You can only register a shared Runner if you are an admin of the GitLab instance.
-You can only register a shared Runner if you are an admin on the linked
-GitLab instance.
+1. Grab the shared-Runner token on the `admin/runners` page
-Grab the shared-Runner token on the `admin/runners` page of your GitLab CI
-instance.
+ ![Shared Runners admin area](img/shared_runners_admin.png)
-![shared token](shared_runner.png)
+1. [Register the Runner][register]
-Now simply register the Runner as any Runner:
+Shared Runners are enabled by default as of GitLab 8.2, but can be disabled
+with the **Disable shared Runners** button which is present under each project's
+**Settings ➔ Pipelines** page. Previous versions of GitLab defaulted shared
+Runners to disabled.
-```
-sudo gitlab-ci-multi-runner register
-```
-
-Shared Runners are enabled by default as of GitLab 8.2, but can be disabled with the
-`DISABLE SHARED RUNNERS` button. Previous versions of GitLab defaulted shared Runners to
-disabled.
-
-## Registering a Specific Runner
+## Registering a specific Runner
Registering a specific can be done in two ways:
1. Creating a Runner with the project registration token
1. Converting a shared Runner into a specific Runner (one-way, admin only)
-There are several ways to create a Runner instance. The steps below only
-concern registering the Runner on GitLab CI.
-
-### Registering a Specific Runner with a Project Registration token
+### Registering a specific Runner with a project registration token
To create a specific Runner without having admin rights to the GitLab instance,
-visit the project you want to make the Runner work for in GitLab CI.
+visit the project you want to make the Runner work for in GitLab:
-Click on the Runner tab and use the registration token you find there to
-setup a specific Runner for this project.
+1. Go to **Settings ➔ Pipelines** to obtain the token
+1. [Register the Runner][register]
-![project Runners in GitLab CI](project_specific.png)
+### Making an existing shared Runner specific
-To register the Runner, run the command below and follow instructions:
+If you are an admin on your GitLab instance, you can turn any shared Runner into
+a specific one, but not the other way around. Keep in mind that this is a one
+way transition.
-```
-sudo gitlab-ci-multi-runner register
-```
+1. Go to the Runners in the admin area **Overview ➔ Runners** (`/admin/runners`)
+ and find your Runner
+1. Enable any projects under **Restrict projects for this Runner** to be used
+ with the Runner
-### Lock a specific Runner from being enabled for other projects
+From now on, the shared Runner will be specific to those projects.
+
+## Locking a specific Runner from being enabled for other projects
You can configure a Runner to assign it exclusively to a project. When a
Runner is locked this way, it can no longer be enabled for other projects.
-This setting is available on each Runner in *Project Settings* > *Runners*.
+This setting can be enabled the first time you [register a Runner][register] and
+can be changed afterwards under each Runner's settings.
+
+To lock/unlock a Runner:
+
+1. Visit your project's **Settings ➔ Pipelines**
+1. Find the Runner you wish to lock/unlock and make sure it's enabled
+1. Click the pencil button
+1. Check the **Lock to current projects** option
+1. Click **Save changes** for the changes to take effect
-### Making an existing Shared Runner Specific
+## How shared Runners pick jobs
-If you are an admin on your GitLab instance,
-you can make any shared Runner a specific Runner, _but you can not
-make a specific Runner a shared Runner_.
+Shared Runners abide to a process queue we call fair usage. The fair usage
+algorithm tries to assign jobs to shared Runners from projects that have the
+lowest number of jobs currently running on shared Runners.
-To make a shared Runner specific, go to the Runner page (`/admin/runners`)
-and find your Runner. Add any projects on the left to make this Runner
-run exclusively for these projects, therefore making it a specific Runner.
+**Example 1**
-![making a shared Runner specific](shared_to_specific_admin.png)
+We have following jobs in queue:
-## Using Shared Runners Effectively
+- job 1 for project 1
+- job 2 for project 1
+- job 3 for project 1
+- job 4 for project 2
+- job 5 for project 2
+- job 6 for project 3
+
+With the fair usage algorithm jobs are assigned in following order:
+
+1. We choose job 1, because project 1 doesn't run currently any jobs and has the lowest job number from projects that doesn't run jobs
+1. We choose job 4, because project 2 doesn't run currently any jobs and has the lowest job number from projects that doesn't run jobs
+1. We choose job 6, because project 3 doesn't run currently any jobs and has the lowest job number from projects that doesn't run jobs
+1. We choose job 2, because project 1 as other it runs 1 job
+1. We choose job 5, because project 2 runs 1 job, where project 1 runs 2 jobs now
+1. We choose job 3, because project 1 and runs 2 jobs
+
+---
+
+**Example 2**
+
+We have following jobs in queue:
+
+- job 1 for project 1
+- job 2 for project 1
+- job 3 for project 1
+- job 4 for project 2
+- job 5 for project 2
+- job 6 for project 3
+
+With the fair usage algorithm jobs are assigned in following order:
+
+1. We choose job 1, because project 1 doesn't run currently any jobs and has the lowest job number from projects that doesn't run jobs
+1. We finish job 1
+1. We choose job 2, because project 1 doesn't run currently any jobs and has the lowest job number from projects that doesn't run jobs
+1. We choose job 4, because project 2 doesn't run currently any jobs and has the lowest job number from projects that doesn't run jobs
+1. We finish job 4
+1. We choose job 5, because project 2 doesn't run currently any jobs and has the lowest job number from projects that doesn't run jobs
+1. We choose job 6, because project 3 doesn't run currently any jobs
+1. We choose job 3, because project 1, 2 and 3 runs exactly one job now
+
+## Using shared Runners effectively
If you are planning to use shared Runners, there are several things you
should keep in mind.
-### Use Tags
+### Using tags
You must setup a Runner to be able to run all the different types of jobs
that it may encounter on the projects it's shared over. This would be
@@ -130,17 +174,27 @@ shared Runners will only run the jobs they are equipped to run.
For instance, at GitLab we have Runners tagged with "rails" if they contain
the appropriate dependencies to run Rails test suites.
-### Prevent Runner with tags from picking jobs without tags
+### Preventing Runners with tags from picking jobs without tags
You can configure a Runner to prevent it from picking jobs with tags when
-the Runner does not have tags assigned. This setting is available on each
-Runner in *Project Settings* > *Runners*.
+the Runner does not have tags assigned. This setting can be enabled the first
+time you [register a Runner][register] and can be changed afterwards under
+each Runner's settings.
+
+To make a Runner pick tagged/untagged jobs:
+
+1. Visit your project's **Settings ➔ Pipelines**
+1. Find the Runner you wish and make sure it's enabled
+1. Click the pencil button
+1. Check the **Run untagged jobs** option
+1. Click **Save changes** for the changes to take effect
### Be careful with sensitive information
If you can run a job on a Runner, you can get access to any code it runs
and get the token of the Runner. With shared Runners, this means that anyone
-that runs jobs on the Runner, can access anyone else's code that runs on the Runner.
+that runs jobs on the Runner, can access anyone else's code that runs on the
+Runner.
In addition, because you can get access to the Runner token, it is possible
to create a clone of a Runner and submit false jobs, for example.
@@ -160,3 +214,7 @@ project.
Mentioned briefly earlier, but the following things of Runners can be exploited.
We're always looking for contributions that can mitigate these
[Security Considerations](https://docs.gitlab.com/runner/security/).
+
+[install]: http://docs.gitlab.com/runner/install/
+[fifo]: https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)
+[register]: http://docs.gitlab.com/runner/register/
diff --git a/doc/ci/runners/img/shared_runners_admin.png b/doc/ci/runners/img/shared_runners_admin.png
new file mode 100644
index 00000000000..e049b339b36
--- /dev/null
+++ b/doc/ci/runners/img/shared_runners_admin.png
Binary files differ
diff --git a/doc/ci/runners/project_specific.png b/doc/ci/runners/project_specific.png
deleted file mode 100644
index c812defa67b..00000000000
--- a/doc/ci/runners/project_specific.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/runners/shared_runner.png b/doc/ci/runners/shared_runner.png
deleted file mode 100644
index 31574a17764..00000000000
--- a/doc/ci/runners/shared_runner.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index cb646827fb4..7ec7136d8c6 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -4,15 +4,22 @@
- [Introduced][ci-229] in GitLab CE 7.14.
- GitLab 8.12 has a completely redesigned job permissions system. Read all
about the [new model and its implications](../../user/project/new_ci_build_permissions_model.md#job-triggers).
-- GitLab 9.0 introduced a trigger ownership to solve permission problems.
-Triggers can be used to force a rebuild of a specific `ref` (branch or tag)
-with an API call.
+Triggers can be used to force a pipeline rerun of a specific `ref` (branch or
+tag) with an API call.
-## Add a trigger
+## Authentication tokens
+
+The following methods of authentication are supported.
+
+### Trigger token
+
+A unique trigger token can be obtained when [adding a new trigger](#adding-a-new-trigger).
+
+## Adding a new trigger
You can add a new trigger by going to your project's
-**Settings ➔ Pipelines ➔ Triggers**. The **Add trigger** button will
+**Settings ➔ Pipelines** under **Triggers**. The **Add trigger** button will
create a new token which you can then use to trigger a rerun of this
particular project's pipeline.
@@ -22,7 +29,10 @@ overview of the time the triggers were last used.
![Triggers page overview](img/triggers_page.png)
-## Take ownership
+## Taking ownership of a trigger
+
+> **Note**:
+GitLab 9.0 introduced a trigger ownership to solve permission problems.
Each created trigger when run will impersonate their associated user including
their access to projects and their project permissions.
@@ -30,26 +40,20 @@ their access to projects and their project permissions.
You can take ownership of existing triggers by clicking *Take ownership*.
From now on the trigger will be run as you.
-## Legacy triggers
-
-Old triggers, created before 9.0 will be marked as Legacy. Triggers with
-the legacy label do not have an associated user and only have access
-to the current project.
-
-Legacy trigger are considered deprecated and will be removed
-with one of the future versions of GitLab.
-
-## Revoke a trigger
+## Revoking a trigger
You can revoke a trigger any time by going at your project's
-**Settings > Triggers** and hitting the **Revoke** button. The action is
-irreversible.
+**Settings ➔ Pipelines** under **Triggers** and hitting the **Revoke** button.
+The action is irreversible.
-## Trigger a pipeline
+## Triggering a pipeline
-> **Note**:
-Valid refs are only the branches and tags. If you pass a commit SHA as a ref,
-it will not trigger a job.
+> **Notes**:
+- Valid refs are only the branches and tags. If you pass a commit SHA as a ref,
+ it will not trigger a job.
+- If your project is public, passing the token in plain text is probably not the
+ wisest idea, so you might want to use a
+ [secret variable](../variables/README.md#secret-variables) for that purpose.
To trigger a job you need to send a `POST` request to GitLab's API endpoint:
@@ -57,11 +61,11 @@ To trigger a job you need to send a `POST` request to GitLab's API endpoint:
POST /projects/:id/trigger/pipeline
```
-The required parameters are the trigger's `token` and the Git `ref` on which
-the trigger will be performed. Valid refs are the branch and the tag. The `:id`
-of a project can be found by [querying the API](../../api/projects.md)
-or by visiting the **Pipelines** settings page which provides
-self-explanatory examples.
+The required parameters are the [trigger's `token`](#authentication-tokens)
+and the Git `ref` on which the trigger will be performed. Valid refs are the
+branch and the tag. The `:id` of a project can be found by
+[querying the API](../../api/projects.md) or by visiting the **Pipelines**
+settings page which provides self-explanatory examples.
When a rerun of a pipeline is triggered, the information is exposed in GitLab's
UI under the **Jobs** page and the jobs are marked as triggered 'by API'.
@@ -78,46 +82,7 @@ below.
---
-See the [Examples](#examples) section for more details on how to actually
-trigger a rebuild.
-
-## Trigger a pipeline from webhook
-
-> Introduced in GitLab 8.14.
-
-To trigger a job from webhook of another project you need to add the following
-webhook url for Push and Tag push events:
-
-```
-https://gitlab.example.com/api/v4/projects/:id/ref/:ref/trigger/pipeline?token=TOKEN
-```
-
-> **Note**:
-- `ref` should be passed as part of url in order to take precedence over `ref`
- from webhook body that designates the branchref that fired the trigger in the source repository.
-- `ref` should be url encoded if contains slashes.
-
-## Pass job variables to a trigger
-
-You can pass any number of arbitrary variables in the trigger API call and they
-will be available in GitLab CI so that they can be used in your `.gitlab-ci.yml`
-file. The parameter is of the form:
-
-```
-variables[key]=value
-```
-
-This information is also exposed in the UI.
-
-![Job variables in UI](img/trigger_variables.png)
-
----
-
-See the [Examples](#examples) section below for more details.
-
-## Examples
-
-Using cURL you can trigger a rebuild with minimal effort, for example:
+By using cURL you can trigger a pipeline rerun with minimal effort, for example:
```bash
curl --request POST \
@@ -135,8 +100,6 @@ curl --request POST \
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline?token=TOKEN&ref=master"
```
-### Triggering a pipeline within `.gitlab-ci.yml`
-
You can also benefit by using triggers in your `.gitlab-ci.yml`. Let's say that
you have two projects, A and B, and you want to trigger a rebuild on the `master`
branch of project B whenever a tag on project A is created. This is the job you
@@ -156,14 +119,37 @@ Now, whenever a new tag is pushed on project A, the job will run and the
`stage: deploy` ensures that this job will run only after all jobs with
`stage: test` complete successfully.
-_**Note:** If your project is public, passing the token in plain text is
-probably not the wisest idea, so you might want to use a
-[secure variable](../variables/README.md#user-defined-variables-secure-variables)
-for that purpose._
+## Triggering a pipeline from a webhook
-### Making use of trigger variables
+> **Notes**:
+- Introduced in GitLab 8.14.
+- `ref` should be passed as part of the URL in order to take precedence over
+ `ref` from the webhook body that designates the branch ref that fired the
+ trigger in the source repository.
+- `ref` should be URL-encoded if it contains slashes.
-Using trigger variables can be proven useful for a variety of reasons.
+To trigger a job from a webhook of another project you need to add the following
+webhook URL for Push and Tag events (change the project ID, ref and token):
+
+```
+https://gitlab.example.com/api/v4/projects/9/ref/master/trigger/pipeline?token=TOKEN
+```
+
+## Making use of trigger variables
+
+You can pass any number of arbitrary variables in the trigger API call and they
+will be available in GitLab CI so that they can be used in your `.gitlab-ci.yml`
+file. The parameter is of the form:
+
+```
+variables[key]=value
+```
+
+This information is also exposed in the UI.
+
+![Job variables in UI](img/trigger_variables.png)
+
+Using trigger variables can be proven useful for a variety of reasons:
* Identifiable jobs. Since the variable is exposed in the UI you can know
why the rebuild was triggered if you pass a variable that explains the
@@ -208,15 +194,7 @@ curl --request POST \
https://gitlab.example.com/api/v4/projects/9/trigger/pipeline
```
-### Using a webhook to trigger a pipeline
-
-You can add the following webhook to another project in order to trigger a job:
-
-```
-https://gitlab.example.com/api/v4/projects/9/ref/master/trigger/pipeline?token=TOKEN&variables[UPLOAD_TO_S3]=true
-```
-
-### Using cron to trigger nightly pipelines
+## Using cron to trigger nightly pipelines
>**Note:**
The following behavior can also be achieved through GitLab's UI with
@@ -230,4 +208,18 @@ branch of project with ID `9` every night at `00:30`:
30 0 * * * curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline
```
+## Legacy triggers
+
+Old triggers, created before GitLab 9.0 will be marked as legacy.
+
+Triggers with the legacy label do not have an associated user and only have
+access to the current project. They are considered deprecated and will be
+removed with one of the future versions of GitLab. You are advised to
+[take ownership](#taking-ownership) of any legacy triggers.
+
+[ee-2017]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2017
[ci-229]: https://gitlab.com/gitlab-org/gitlab-ci/merge_requests/229
+[ee]: https://about.gitlab.com/gitlab-ee/
+[variables]: ../variables/README.md
+[predef]: ../variables/README.md#predefined-variables-environment-variables
+[registry]: ../../user/project/container_registry.md
diff --git a/doc/ci/triggers/img/triggers_page.png b/doc/ci/triggers/img/triggers_page.png
index eafd8519a23..7dc8f91cf7e 100644
--- a/doc/ci/triggers/img/triggers_page.png
+++ b/doc/ci/triggers/img/triggers_page.png
Binary files differ
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 76ba78ea7be..d1f9881e51b 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -431,3 +431,4 @@ export CI_REGISTRY_PASSWORD="longalfanumstring"
[protected branches]: ../../user/project/protected_branches.md
[protected tags]: ../../user/project/protected_tags.md
[shellexecutors]: https://docs.gitlab.com/runner/executors/
+[eep]: https://about.gitlab.com/gitlab-ee/ "Available only in GitLab Enterprise Edition Premium"
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 5338ccb9d3a..197a92905c8 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -129,7 +129,8 @@ We _highly_ recommend the use of PostgreSQL instead of MySQL/MariaDB as not all
features of GitLab may work with MySQL/MariaDB. For example, MySQL does not have
the right features to support nested groups in an efficient manner; see
<https://gitlab.com/gitlab-org/gitlab-ce/issues/30472> for more information
-about this. Existing users using GitLab with MySQL/MariaDB are advised to
+about this. GitLab Geo also does [not support MySQL](https://docs.gitlab.com/ee/gitlab-geo/database.html#mysql-replication).
+Existing users using GitLab with MySQL/MariaDB are advised to
migrate to PostgreSQL instead.
The server running the database should have _at least_ 5-10 GB of storage
diff --git a/doc/user/project/img/protected_branches_delete.png b/doc/user/project/img/protected_branches_delete.png
new file mode 100644
index 00000000000..cfdfe6c6c29
--- /dev/null
+++ b/doc/user/project/img/protected_branches_delete.png
Binary files differ
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index 7650020b37e..0570d9f471f 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -94,8 +94,33 @@ all matching branches:
![Protected branch matches](img/protected_branches_matches.png)
+## Deleting a protected branch
+
+> [Introduced][ce-21393] in GitLab 9.3.
+
+From time to time, it may be required to delete or clean up branches that are
+protected.
+
+User with [Master permissions][perm] and up can manually delete protected
+branches via GitLab's web interface:
+
+1. Visit **Repository > Branches**
+1. Click on the delete icon next to the branch you wish to delete
+1. In order to prevent accidental deletion, an additional confirmation is
+ required
+
+ ![Delete protected branches](img/protected_branches_delete.png)
+
+Deleting a protected branch is only allowed via the web interface, not via Git.
+This means that you can't accidentally delete a protected branch from your
+command line or a Git client application.
+
## Changelog
+**9.2**
+
+- Allow deletion of protected branches via the web interface [gitlab-org/gitlab-ce#21393][ce-21393]
+
**8.11**
- Allow creating protected branches that can't be pushed to [gitlab-org/gitlab-ce!5081][ce-5081]
@@ -110,4 +135,6 @@ all matching branches:
[ce-4665]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4665 "Allow specifying protected branches using wildcards"
[ce-4892]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4892 "Allow developers to merge into a protected branch without having push access"
[ce-5081]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5081 "Allow creating protected branches that can't be pushed to"
+[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
diff --git a/features/steps/project/project_group_links.rb b/features/steps/project/project_group_links.rb
index 739a85e5fa4..5280a38ce81 100644
--- a/features/steps/project/project_group_links.rb
+++ b/features/steps/project/project_group_links.rb
@@ -5,18 +5,19 @@ class Spinach::Features::ProjectGroupLinks < Spinach::FeatureSteps
include Select2Helper
step 'I should see project already shared with group "Ops"' do
- page.within '.enabled-groups' do
+ page.within '.project-members-groups' do
expect(page).to have_content "Ops"
end
end
step 'I should see project is not shared with group "Market"' do
- page.within '.enabled-groups' do
+ page.within '.project-members-groups' do
expect(page).not_to have_content "Market"
end
end
step 'I select group "Market" for share' do
+ click_link 'Share with group'
group = Group.find_by(path: 'market')
select2(group.id, from: "#link_group_id")
select "Master", from: 'link_group_access'
@@ -24,7 +25,7 @@ class Spinach::Features::ProjectGroupLinks < Spinach::FeatureSteps
end
step 'I should see project is shared with group "Market"' do
- page.within '.enabled-groups' do
+ page.within '.project-members-groups' do
expect(page).to have_content "Market"
end
end
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 88f91c07194..d767af36e8e 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -45,6 +45,7 @@ module API
end
before { allow_access_with_scope :api }
+ before { header['X-Frame-Options'] = 'SAMEORIGIN' }
before { Gitlab::I18n.locale = current_user&.preferred_language }
after { Gitlab::I18n.use_default_locale }
diff --git a/lib/api/files.rb b/lib/api/files.rb
index 25b0968a271..521287ee2b4 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -25,7 +25,7 @@ module API
@blob = @repo.blob_at(@commit.sha, params[:file_path])
not_found!('File') unless @blob
- @blob.load_all_data!(@repo)
+ @blob.load_all_data!
end
def commit_response(attrs)
diff --git a/lib/api/v3/files.rb b/lib/api/v3/files.rb
index c76acc86504..7b4b3448b6d 100644
--- a/lib/api/v3/files.rb
+++ b/lib/api/v3/files.rb
@@ -56,7 +56,7 @@ module API
blob = repo.blob_at(commit.sha, params[:file_path])
not_found!('File') unless blob
- blob.load_all_data!(repo)
+ blob.load_all_data!
status(200)
{
diff --git a/lib/gitlab/blame.rb b/lib/gitlab/blame.rb
index d62bc50ce78..169aac79854 100644
--- a/lib/gitlab/blame.rb
+++ b/lib/gitlab/blame.rb
@@ -40,7 +40,7 @@ module Gitlab
end
def highlighted_lines
- @blob.load_all_data!(repository)
+ @blob.load_all_data!
@highlighted_lines ||=
Gitlab::Highlight.highlight(@blob.path, @blob.data, repository: repository).lines
end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 2aef7fdaa35..4212a0dbe2e 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -58,19 +58,19 @@ module Gitlab
diff_refs&.head_sha
end
- def content_sha
- return old_content_sha if deleted_file?
- return @content_sha if defined?(@content_sha)
+ def new_content_sha
+ return if deleted_file?
+ return @new_content_sha if defined?(@new_content_sha)
refs = diff_refs || fallback_diff_refs
- @content_sha = refs&.head_sha
+ @new_content_sha = refs&.head_sha
end
- def content_commit
- return @content_commit if defined?(@content_commit)
+ def new_content_commit
+ return @new_content_commit if defined?(@new_content_commit)
- sha = content_sha
- @content_commit = repository.commit(sha) if sha
+ sha = new_content_commit
+ @new_content_commit = repository.commit(sha) if sha
end
def old_content_sha
@@ -88,13 +88,13 @@ module Gitlab
@old_content_commit = repository.commit(sha) if sha
end
- def blob
- return @blob if defined?(@blob)
+ def new_blob
+ return @new_blob if defined?(@new_blob)
- sha = content_sha
- return @blob = nil unless sha
+ sha = new_content_sha
+ return @new_blob = nil unless sha
- repository.blob_at(sha, file_path)
+ @new_blob = repository.blob_at(sha, file_path)
end
def old_blob
@@ -106,6 +106,18 @@ module Gitlab
@old_blob = repository.blob_at(sha, old_path)
end
+ def content_sha
+ new_content_sha || old_content_sha
+ end
+
+ def content_commit
+ new_content_commit || old_content_commit
+ end
+
+ def blob
+ new_blob || old_blob
+ end
+
attr_writer :highlighted_diff_lines
# Array of Gitlab::Diff::Line objects
@@ -153,6 +165,18 @@ module Gitlab
def file_identifier
"#{file_path}-#{new_file?}-#{deleted_file?}-#{renamed_file?}"
end
+
+ def diffable?
+ repository.attributes(file_path).fetch('diff') { true }
+ end
+
+ def binary?
+ old_blob&.binary? || new_blob&.binary?
+ end
+
+ def text?
+ !binary?
+ end
end
end
end
diff --git a/lib/gitlab/diff/file_collection/merge_request_diff.rb b/lib/gitlab/diff/file_collection/merge_request_diff.rb
index 9a58b500a2c..fcda1fe2233 100644
--- a/lib/gitlab/diff/file_collection/merge_request_diff.rb
+++ b/lib/gitlab/diff/file_collection/merge_request_diff.rb
@@ -66,10 +66,7 @@ module Gitlab
end
def cacheable?(diff_file)
- @merge_request_diff.present? &&
- diff_file.blob &&
- diff_file.blob.text? &&
- @project.repository.diffable?(diff_file.blob)
+ @merge_request_diff.present? && diff_file.text? && diff_file.diffable?
end
def cache_key
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index ed2f541977a..b669ee5b799 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -42,9 +42,9 @@ module Gitlab
rich_line =
if diff_line.unchanged? || diff_line.added?
- new_lines[diff_line.new_pos - 1]
+ new_lines[diff_line.new_pos - 1]&.html_safe
elsif diff_line.removed?
- old_lines[diff_line.old_pos - 1]
+ old_lines[diff_line.old_pos - 1]&.html_safe
end
# Only update text if line is found. This will prevent
@@ -60,13 +60,18 @@ module Gitlab
end
def old_lines
- return unless diff_file
- @old_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_old_sha, diff_old_path)
+ @old_lines ||= highlighted_blob_lines(diff_file.old_blob)
end
def new_lines
- return unless diff_file
- @new_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_new_sha, diff_new_path)
+ @new_lines ||= highlighted_blob_lines(diff_file.new_blob)
+ end
+
+ def highlighted_blob_lines(blob)
+ return [] unless blob
+
+ blob.load_all_data!
+ Gitlab::Highlight.highlight(blob.path, blob.data, repository: repository).lines
end
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 9d6adbdb4ac..85695d0a4df 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -962,11 +962,6 @@ module Gitlab
end
end
- # Checks if the blob should be diffable according to its attributes
- def diffable?(blob)
- attributes(blob.path).fetch('diff') { blob.text? }
- end
-
# Returns the Git attributes for the given file path.
#
# See `Gitlab::Git::Attributes` for more information.
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index 83bc230df3e..6b24da030df 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -5,14 +5,6 @@ module Gitlab
highlight(blob_content, continue: false, plain: plain)
end
- def self.highlight_lines(repository, ref, file_name)
- blob = repository.blob_at(ref, file_name)
- return [] unless blob
-
- blob.load_all_data!(repository)
- highlight(file_name, blob.data, repository: repository).lines.map!(&:html_safe)
- end
-
attr_reader :blob_name
def initialize(blob_name, blob_content, repository: nil)
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index f7ac48f7dbd..328dd17e452 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -6,9 +6,11 @@ module Gitlab
'en' => 'English',
'es' => 'Español',
'de' => 'Deutsch',
+ 'pt_BR' => 'Português(Brasil)',
'zh_CN' => '简体中文',
'zh_HK' => '繁體中文(香港)',
- 'zh_TW' => '繁體中文(臺灣)'
+ 'zh_TW' => '繁體中文(臺灣)',
+ 'bg' => 'български'
}.freeze
def available_locales
diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb
index 9ff6829cd49..10eb99fb461 100644
--- a/lib/gitlab/path_regex.rb
+++ b/lib/gitlab/path_regex.rb
@@ -49,6 +49,7 @@ module Gitlab
sent_notifications
services
snippets
+ system
teams
u
unicorn_test
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
new file mode 100644
index 00000000000..e6caf83252d
--- /dev/null
+++ b/locale/bg/gitlab.po
@@ -0,0 +1,260 @@
+# Lyubomir Vasilev <lyubomirv@abv.bg>, 2017. #zanata
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab 1.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-05-04 19:24-0500\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"PO-Revision-Date: 2017-06-05 09:40-0400\n"
+"Last-Translator: Lyubomir Vasilev <lyubomirv@abv.bg>\n"
+"Language-Team: Bulgarian\n"
+"Language: bg\n"
+"X-Generator: Zanata 3.9.6\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+msgid "ByAuthor|by"
+msgstr "от"
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] "Подаване"
+msgstr[1] "Подавания"
+
+msgid ""
+"Cycle Analytics gives an overview of how much time it takes to go from idea "
+"to production in your project."
+msgstr ""
+"Анализът на циклите дава общ поглед върху това колко време е нужно на една "
+"идея да се превърне в завършена функционалност в проекта."
+
+msgid "CycleAnalyticsStage|Code"
+msgstr "Програмиране"
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr "Проблем"
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr "Планиране"
+
+msgid "CycleAnalyticsStage|Production"
+msgstr "Издаване"
+
+msgid "CycleAnalyticsStage|Review"
+msgstr "Преглед и одобрение"
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr "Подготовка за издаване"
+
+msgid "CycleAnalyticsStage|Test"
+msgstr "Тестване"
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] "Внедряване"
+msgstr[1] "Внедрявания"
+
+msgid "FirstPushedBy|First"
+msgstr "Първо"
+
+msgid "FirstPushedBy|pushed by"
+msgstr "изпращане на промени от"
+
+msgid "From issue creation until deploy to production"
+msgstr "От създаването на проблема до внедряването в крайната версия"
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+"От прилагането на заявката за сливане до внедряването в крайната версия"
+
+msgid "Introducing Cycle Analytics"
+msgstr "Представяме Ви анализът на циклите"
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] "Последния %d ден"
+msgstr[1] "Последните %d дни"
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] "Ограничено до показване на последното %d събитие"
+msgstr[1] "Ограничено до показване на последните %d събития"
+
+msgid "Median"
+msgstr "Медиана"
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] "Нов проблем"
+msgstr[1] "Нови проблема"
+
+msgid "Not available"
+msgstr "Не е налично"
+
+msgid "Not enough data"
+msgstr "Няма достатъчно данни"
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr "Отворен"
+
+msgid "Pipeline Health"
+msgstr "Състояние"
+
+msgid "ProjectLifecycle|Stage"
+msgstr "Етап"
+
+msgid "Read more"
+msgstr "Прочетете повече"
+
+msgid "Related Commits"
+msgstr "Свързани подавания"
+
+msgid "Related Deployed Jobs"
+msgstr "Свързани задачи за внедряване"
+
+msgid "Related Issues"
+msgstr "Свързани проблеми"
+
+msgid "Related Jobs"
+msgstr "Свързани задачи"
+
+msgid "Related Merge Requests"
+msgstr "Свързани заявки за сливане"
+
+msgid "Related Merged Requests"
+msgstr "Свързани приложени заявки за сливане"
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] "Показване на %d събитие"
+msgstr[1] "Показване на %d събития"
+
+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 ""
+"Етапът на програмиране показва времето от първото подаване до създаването на "
+"заявката за сливане. Данните ще бъдат добавени тук автоматично след като "
+"бъде създадена първата заявка за сливане."
+
+msgid "The collection of events added to the data gathered for that stage."
+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 phase of the development lifecycle."
+msgstr "Етапът от цикъла на разработка"
+
+msgid ""
+"The planning stage shows the time from the previous step to pushing your "
+"first commit. This time will be added automatically once you push your first "
+"commit."
+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 ""
+"Етапът на издаване показва общото време, което е нужно от създаването на "
+"проблем до внедряването на кода в крайната версия."
+
+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 ""
+"Етапът на преглед и одобрение показва времето от създаването на заявката за "
+"сливане до прилагането ѝ. Данните ще бъдат добавени автоматично след като "
+"приложите първата си заявка за сливане."
+
+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 ""
+"Етапът на подготовка за издаване показва времето между прилагането на "
+"заявката за сливане и внедряването на кода в средата на работещата крайна "
+"версия. Данните ще бъдат добавени автоматично след като направите първото си "
+"внедряване в крайната версия."
+
+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 ""
+"Етапът на тестване показва времето, което е нужно на „Gitlab CI“ да изпълни "
+"всички задачи за свързаната заявка за сливане. Данните ще бъдат добавени "
+"автоматично след като приключи изпълнените на първата Ви такава задача."
+
+msgid "The time taken by each data entry gathered by that stage."
+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 "Time before an issue gets scheduled"
+msgstr "Време преди един проблем да бъде планиран за работа"
+
+msgid "Time before an issue starts implementation"
+msgstr "Време преди работата по проблем да започне"
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+"Време между създаване на заявка за сливане и прилагането/отхвърлянето ѝ"
+
+msgid "Time until first merge request"
+msgstr "Време преди първата заявка за сливане"
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] "час"
+msgstr[1] "часа"
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] "мин"
+msgstr[1] "мин"
+
+msgid "Time|s"
+msgstr "сек"
+
+msgid "Total Time"
+msgstr "Общо време"
+
+msgid "Total test time for all commits/merges"
+msgstr "Общо време за тестване на всички подавания/сливания"
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr "Искате ли да видите данните? Помолете администратор за достъп."
+
+msgid "We don't have enough data to show this stage."
+msgstr "Няма достатъчно данни за този етап."
+
+msgid "You need permission."
+msgstr "Нуждаете се от разрешение."
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] "ден"
+msgstr[1] "дни"
+
diff --git a/locale/bg/gitlab.po.time_stamp b/locale/bg/gitlab.po.time_stamp
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/locale/bg/gitlab.po.time_stamp
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 60a0c219e00..f9c14210958 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
Binary files differ
diff --git a/locale/en/gitlab.po b/locale/en/gitlab.po
index fca2bc15b1f..ed0ccc61e67 100644
--- a/locale/en/gitlab.po
+++ b/locale/en/gitlab.po
@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2017-06-07 12:14+0200\n"
+"PO-Revision-Date: 2017-04-12 22:36-0500\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: English\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"Last-Translator: Bob Van Landuyt <bob@gitlab.com>\n"
-"X-Generator: Poedit 2.0.2\n"
+"\n"
msgid "About auto deploy"
msgstr ""
@@ -41,6 +41,9 @@ msgstr ""
msgid "Archived project! Repository is read-only"
msgstr ""
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
msgid "Branch"
msgid_plural "Branches"
msgstr[0] ""
@@ -58,6 +61,9 @@ msgstr ""
msgid "CI configuration"
msgstr ""
+msgid "Cancel"
+msgstr ""
+
msgid "Changelog"
msgstr ""
@@ -162,6 +168,9 @@ msgstr ""
msgid "CreateNewFork|Fork"
msgstr ""
+msgid "Cron Timezone"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -195,11 +204,17 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "Delete"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Description"
+msgstr ""
+
msgid "Directory name"
msgstr ""
@@ -224,9 +239,24 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
msgid "Files"
msgstr ""
+msgid "Filter"
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -266,6 +296,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Interval Pattern"
+msgstr ""
+
msgid "Introducing Cycle Analytics"
msgstr ""
@@ -280,6 +313,9 @@ msgid_plural "Last %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "Last Pipeline"
+msgstr ""
+
msgid "Last Update"
msgstr ""
@@ -308,6 +344,9 @@ msgid_plural "New Issues"
msgstr[0] ""
msgstr[1] ""
+msgid "New Pipeline Schedule"
+msgstr ""
+
msgid "New branch"
msgstr ""
@@ -332,6 +371,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No schedules"
+msgstr ""
+
msgid "Not available"
msgstr ""
@@ -395,9 +437,45 @@ msgstr ""
msgid "OpenedNDaysAgo|Opened"
msgstr ""
+msgid "Owner"
+msgstr ""
+
msgid "Pipeline Health"
msgstr ""
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr ""
@@ -488,12 +566,24 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
msgid "Search branches and tags"
msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
msgid "Set a password on your account to pull or push via %{protocol}"
msgstr ""
@@ -531,6 +621,9 @@ msgstr[1] ""
msgid "Tags"
msgstr ""
+msgid "Target Branch"
+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 ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 78d28d69885..1bbc413e24c 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
Binary files differ
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 483412baa05..c967b720885 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-06-07 17:36+0200\n"
-"PO-Revision-Date: 2017-06-07 17:36+0200\n"
+"POT-Creation-Date: 2017-06-08 09:42+0200\n"
+"PO-Revision-Date: 2017-06-08 09:42+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@@ -42,6 +42,9 @@ msgstr ""
msgid "Archived project! Repository is read-only"
msgstr ""
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
msgid "Branch"
msgid_plural "Branches"
msgstr[0] ""
@@ -59,6 +62,9 @@ msgstr ""
msgid "CI configuration"
msgstr ""
+msgid "Cancel"
+msgstr ""
+
msgid "Changelog"
msgstr ""
@@ -163,6 +169,9 @@ msgstr ""
msgid "CreateNewFork|Fork"
msgstr ""
+msgid "Cron Timezone"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -196,11 +205,17 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "Delete"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Description"
+msgstr ""
+
msgid "Directory name"
msgstr ""
@@ -225,9 +240,24 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
msgid "Files"
msgstr ""
+msgid "Filter"
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -267,6 +297,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Interval Pattern"
+msgstr ""
+
msgid "Introducing Cycle Analytics"
msgstr ""
@@ -281,6 +314,9 @@ msgid_plural "Last %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "Last Pipeline"
+msgstr ""
+
msgid "Last Update"
msgstr ""
@@ -309,6 +345,9 @@ msgid_plural "New Issues"
msgstr[0] ""
msgstr[1] ""
+msgid "New Pipeline Schedule"
+msgstr ""
+
msgid "New branch"
msgstr ""
@@ -333,6 +372,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No schedules"
+msgstr ""
+
msgid "Not available"
msgstr ""
@@ -396,9 +438,45 @@ msgstr ""
msgid "OpenedNDaysAgo|Opened"
msgstr ""
+msgid "Owner"
+msgstr ""
+
msgid "Pipeline Health"
msgstr ""
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr ""
@@ -489,12 +567,24 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
msgid "Search branches and tags"
msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
msgid "Set a password on your account to pull or push via %{protocol}"
msgstr ""
@@ -532,6 +622,9 @@ msgstr[1] ""
msgid "Tags"
msgstr ""
+msgid "Target Branch"
+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 ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
new file mode 100644
index 00000000000..5ad41f92b64
--- /dev/null
+++ b/locale/pt_BR/gitlab.po
@@ -0,0 +1,260 @@
+# Alexandre Alencar <alexandre.alencar@gmail.com>, 2017. #zanata
+# Fabio Beneditto <fabiobeneditto@gmail.com>, 2017. #zanata
+# Leandro Nunes dos Santos <leandronunes@gmail.com>, 2017. #zanata
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab 1.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-05-04 19:24-0500\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"PO-Revision-Date: 2017-06-05 03:29-0400\n"
+"Last-Translator: Alexandre Alencar <alexandre.alencar@gmail.com>\n"
+"Language-Team: Portuguese (Brazil)\n"
+"Language: pt-BR\n"
+"X-Generator: Zanata 3.9.6\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+msgid "ByAuthor|by"
+msgstr "por"
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] "Commit"
+msgstr[1] "Commits"
+
+msgid ""
+"Cycle Analytics gives an overview of how much time it takes to go from idea "
+"to production in your project."
+msgstr ""
+"A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora "
+"para ir para produção em seu projeto."
+
+msgid "CycleAnalyticsStage|Code"
+msgstr "Código"
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr "Tarefa"
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr "Plano"
+
+msgid "CycleAnalyticsStage|Production"
+msgstr "Produção"
+
+msgid "CycleAnalyticsStage|Review"
+msgstr "Revisão"
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr "Homologação"
+
+msgid "CycleAnalyticsStage|Test"
+msgstr "Teste"
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] "Implantação"
+msgstr[1] "Implantações"
+
+msgid "FirstPushedBy|First"
+msgstr "Primeiro"
+
+msgid "FirstPushedBy|pushed by"
+msgstr "publicado por"
+
+msgid "From issue creation until deploy to production"
+msgstr "Da criação de tarefas até a implantação para a produção"
+
+msgid "From merge request merge until deploy to production"
+msgstr "Da incorporação do merge request até a implantação em produção"
+
+msgid "Introducing Cycle Analytics"
+msgstr "Apresentando a Análise de Ciclo"
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] "Último %d dia"
+msgstr[1] "Últimos %d dias"
+
+msgid "Limited to showing %d event at most"
+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 "Median"
+msgstr "Mediana"
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] "Nova Tarefa"
+msgstr[1] "Novas Tarefas"
+
+msgid "Not available"
+msgstr "Não disponível"
+
+msgid "Not enough data"
+msgstr "Dados insuficientes"
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr "Aberto"
+
+msgid "Pipeline Health"
+msgstr "Saúde da Pipeline"
+
+msgid "ProjectLifecycle|Stage"
+msgstr "Etapa"
+
+msgid "Read more"
+msgstr "Ler mais"
+
+msgid "Related Commits"
+msgstr "Commits Relacionados"
+
+msgid "Related Deployed Jobs"
+msgstr "Jobs Relacionados Incorporados"
+
+msgid "Related Issues"
+msgstr "Tarefas Relacionadas"
+
+msgid "Related Jobs"
+msgstr "Jobs Relacionados"
+
+msgid "Related Merge Requests"
+msgstr "Merge Requests Relacionados"
+
+msgid "Related Merged Requests"
+msgstr "Merge Requests Relacionados"
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] "Mostrando %d evento"
+msgstr[1] "Mostrando %d eventos"
+
+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 ""
+"O estágio de codificação mostra o tempo desde o primeiro commit até a "
+"criação do merge request. \n"
+"Os dados serão automaticamente adicionados aqui uma vez que você tenha "
+"criado seu primeiro merge request."
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+"A coleção de eventos adicionados aos dados coletados para esse estágio."
+
+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 ""
+"O estágio em questão mostra o tempo que leva desde a criação de uma tarefa "
+"até a sua assinatura para um milestone, ou a sua adição para a lista no seu "
+"Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa."
+
+msgid "The phase of the development lifecycle."
+msgstr "A fase do ciclo de vida do desenvolvimento."
+
+msgid ""
+"The planning stage shows the time from the previous step to pushing your "
+"first commit. This time will be added automatically once you push your first "
+"commit."
+msgstr ""
+"A fase de planejamento mostra o tempo do passo anterior até empurrar o seu "
+"primeiro commit. Este tempo será adicionado automaticamente assim que você "
+"realizar seu primeiro commit."
+
+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 ""
+"O estágio de produção mostra o tempo total que leva entre criar uma tarefa e "
+"implantar o código na produção. Os dados serão adicionados automaticamente "
+"até que você complete todo o ciclo de produção."
+
+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 ""
+"A etapa de revisão mostra o tempo de criação de um merge request até que o "
+"merge seja feito. Os dados serão automaticamente adicionados depois que você "
+"fizer seu primeiro merge request."
+
+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 ""
+"O estágio de estágio mostra o tempo entre a fusão do MR e o código de "
+"implantação para o ambiente de produção. Os dados serão automaticamente "
+"adicionados depois de implantar na produção pela primeira vez."
+
+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 ""
+"A fase de teste mostra o tempo que o GitLab CI leva para executar cada "
+"pipeline para o merge request relacionado. Os dados serão automaticamente "
+"adicionados após a conclusão do primeiro pipeline."
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr "O tempo necessário para cada entrada de dados reunida por essa etapa."
+
+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 "Time before an issue gets scheduled"
+msgstr "Tempo até que uma tarefa seja planejada"
+
+msgid "Time before an issue starts implementation"
+msgstr "Tempo até que uma tarefa comece a ser implementada"
+
+msgid "Time between merge request creation and merge/close"
+msgstr "Tempo entre a criação do merge request e o merge/fechamento"
+
+msgid "Time until first merge request"
+msgstr "Tempo até o primeiro merge request"
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] "h"
+msgstr[1] "hs"
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] "min"
+msgstr[1] "mins"
+
+msgid "Time|s"
+msgstr "s"
+
+msgid "Total Time"
+msgstr "Tempo Total"
+
+msgid "Total test time for all commits/merges"
+msgstr "Tempo de teste total para todos os commits/merges"
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr "Precisa visualizar os dados? Solicite acesso ao administrador."
+
+msgid "We don't have enough data to show this stage."
+msgstr "Não temos dados suficientes para mostrar esta fase."
+
+msgid "You need permission."
+msgstr "Você precisa de permissão."
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] "dia"
+msgstr[1] "dias"
+
diff --git a/locale/pt_BR/gitlab.po.time_stamp b/locale/pt_BR/gitlab.po.time_stamp
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/locale/pt_BR/gitlab.po.time_stamp
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index c2d69b122e2..176dd68b52f 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -2,32 +2,188 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gitlab package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
+#
msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-05-04 19:24-0500\n"
"PO-Revision-Date: 2017-05-04 19:24-0500\n"
"Last-Translator: HuangTao <htve@outlook.com>, 2017\n"
-"Language-Team: Chinese (China) (https://www.transifex.com/gitlab-zh/teams/75177/zh_CN/)\n"
+"Language-Team: Chinese (China) (https://www.transifex.com/gitlab-zh/teams/7517"
+"7/zh_CN/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+msgid "About auto deploy"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add License"
+msgstr ""
+
+msgid "Add an SSH key to your profile to pull or push via SSH."
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Archived project! Repository is read-only"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Branch"
+msgid_plural "Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+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 ""
+
+msgid "Branches"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
+msgid "CI configuration"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "提交"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
+#, fuzzy
+msgid "CommitMessage|Add %{file_name}"
+msgstr "提交"
+
+#, fuzzy
+msgid "Commits"
+msgstr "提交"
+
+#, fuzzy
+msgid "Commits|History"
+msgstr "提交"
+
+msgid "Compare"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty bare repository"
+msgstr ""
+
+#, fuzzy
+msgid "Create merge request"
+msgstr "相关的合并请求"
+
+msgid "CreateNewFork|Fork"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+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 ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "周期分析概述了项目从想法到产品实现的各阶段所需的时间。"
msgid "CycleAnalyticsStage|Code"
@@ -51,29 +207,128 @@ msgstr "预发布"
msgid "CycleAnalyticsStage|Test"
msgstr "测试"
+msgid "Delete"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
+msgid "Description"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "首次推送"
msgid "FirstPushedBy|pushed by"
msgstr "推送者:"
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
msgid "From issue creation until deploy to production"
msgstr "从创建议题到部署至生产环境"
msgid "From merge request merge until deploy to production"
msgstr "从合并请求被合并后到部署至生产环境"
+msgid "Go to your fork"
+msgstr ""
+
+msgid "GoToYourFork|Fork"
+msgstr ""
+
+msgid "Home"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
msgid "Introducing Cycle Analytics"
msgstr "周期分析简介"
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "最后 %d 天"
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Update"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "最多显示 %d 个事件"
@@ -81,28 +336,210 @@ msgstr[0] "最多显示 %d 个事件"
msgid "Median"
msgstr "中位数"
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "新议题"
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+#, fuzzy
+msgid "New issue"
+msgstr "新议题"
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
msgid "Not available"
msgstr "数据不足"
msgid "Not enough data"
msgstr "数据不足"
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
msgid "OpenedNDaysAgo|Opened"
msgstr "开始于"
+msgid "Owner"
+msgstr ""
+
msgid "Pipeline Health"
msgstr "流水线健康指标"
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project home"
+msgstr ""
+
+msgid "ProjectFeature|Disabled"
+msgstr ""
+
+msgid "ProjectFeature|Everyone with access"
+msgstr ""
+
+msgid "ProjectFeature|Only team members"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
msgid "ProjectLifecycle|Stage"
msgstr "项目生命周期"
+msgid "ProjectNetworkGraph|Graph"
+msgstr ""
+
msgid "Read more"
msgstr "了解更多"
+#, fuzzy
+msgid "Readme"
+msgstr "了解更多"
+
+msgid "RefSwitcher|Branches"
+msgstr ""
+
+msgid "RefSwitcher|Tags"
+msgstr ""
+
msgid "Related Commits"
msgstr "相关的提交"
@@ -121,67 +558,120 @@ msgstr "相关的合并请求"
msgid "Related Merged Requests"
msgstr "相关已合并的合并请求"
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}"
+msgstr ""
+
+msgid "Set up CI"
+msgstr ""
+
+msgid "Set up Koding"
+msgstr ""
+
+msgid "Set up auto deploy"
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
msgid "Showing %d event"
msgid_plural "Showing %d events"
msgstr[0] "显示 %d 个事件"
-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."
+msgid "Source code"
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Target Branch"
+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 "编码阶段概述了从第一次提交到创建合并请求的时间。创建第一个合并请求后,数据将自动添加到此处。"
msgid "The collection of events added to the data gathered for that stage."
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."
+msgid "The fork relationship has been removed."
+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 phase of the development lifecycle."
msgstr "项目生命周期中的各个阶段。"
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first"
-" commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
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."
+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 "生产阶段概述了从创建一个议题到将代码部署到生产环境的总时间。当完成想法到部署生产的循环,数据将自动添加到此处。"
-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."
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+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 "评审阶段概述了从创建合并请求到被合并的时间。当创建第一个合并请求后,数据将自动添加到此处。"
-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."
+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 "预发布阶段概述了从合并请求被合并到部署至生产环境的总时间。首次部署到生产环境后,数据将自动添加到此处。"
-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."
+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 "测试阶段概述了GitLab CI为相关合并请求运行每个流水线所需的时间。当第一个流水线运行完成后,数据将自动添加到此处。"
msgid "The time taken by each data entry gathered by that stage."
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."
+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 "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "议题被列入日程表的时间"
@@ -194,6 +684,135 @@ msgstr "从创建合并请求到被合并或关闭的时间"
msgid "Time until first merge request"
msgstr "创建第一个合并请求之前的时间"
+#, fuzzy
+msgid "Timeago|%s days ago"
+msgstr "天"
+
+#, fuzzy
+msgid "Timeago|%s days remaining"
+msgstr "天"
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|1 day remaining"
+msgstr "天"
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|a day ago"
+msgstr "天"
+
+msgid "Timeago|a month ago"
+msgstr ""
+
+msgid "Timeago|a week ago"
+msgstr ""
+
+msgid "Timeago|a while"
+msgstr ""
+
+msgid "Timeago|a year ago"
+msgstr ""
+
+msgid "Timeago|about %s hours ago"
+msgstr ""
+
+msgid "Timeago|about a minute ago"
+msgstr ""
+
+msgid "Timeago|about an hour ago"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|in %s days"
+msgstr "天"
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|in 1 day"
+msgstr "天"
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|less than a minute ago"
+msgstr ""
+
msgid "Time|hr"
msgid_plural "Time|hrs"
msgstr[0] "小时"
@@ -211,15 +830,87 @@ msgstr "总时间"
msgid "Total test time for all commits/merges"
msgstr "所有提交和合并的总测试时间"
+msgid "Unstar"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "权限不足。如需查看相关数据,请向管理员申请权限。"
msgid "We don't have enough data to show this stage."
msgstr "该阶段的数据不足,无法显示。"
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You must sign in to star a project"
+msgstr ""
+
msgid "You need permission."
msgstr "您需要相关的权限。"
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "committed"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "天"
+
+msgid "notification emails"
+msgstr ""
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 6d56b2897fa..311d44afb42 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -2,32 +2,188 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gitlab package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
+#
msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-05-04 19:24-0500\n"
"PO-Revision-Date: 2017-05-04 19:24-0500\n"
"Last-Translator: HuangTao <htve@outlook.com>, 2017\n"
-"Language-Team: Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/75177/zh_HK/)\n"
+"Language-Team: Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/"
+"75177/zh_HK/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_HK\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+msgid "About auto deploy"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add License"
+msgstr ""
+
+msgid "Add an SSH key to your profile to pull or push via SSH."
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Archived project! Repository is read-only"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Branch"
+msgid_plural "Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+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 ""
+
+msgid "Branches"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
+msgid "CI configuration"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "提交"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
+#, fuzzy
+msgid "CommitMessage|Add %{file_name}"
+msgstr "提交"
+
+#, fuzzy
+msgid "Commits"
+msgstr "提交"
+
+#, fuzzy
+msgid "Commits|History"
+msgstr "提交"
+
+msgid "Compare"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty bare repository"
+msgstr ""
+
+#, fuzzy
+msgid "Create merge request"
+msgstr "相關的合併請求"
+
+msgid "CreateNewFork|Fork"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+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 ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "週期分析概述了項目從想法到產品實現的各階段所需的時間。"
msgid "CycleAnalyticsStage|Code"
@@ -51,29 +207,128 @@ msgstr "預發布"
msgid "CycleAnalyticsStage|Test"
msgstr "測試"
+msgid "Delete"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
+msgid "Description"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "首次推送"
msgid "FirstPushedBy|pushed by"
msgstr "推送者:"
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
msgid "From issue creation until deploy to production"
msgstr "從創建議題到部署到生產環境"
msgid "From merge request merge until deploy to production"
msgstr "從合併請求的合併到部署至生產環境"
+msgid "Go to your fork"
+msgstr ""
+
+msgid "GoToYourFork|Fork"
+msgstr ""
+
+msgid "Home"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
msgid "Introducing Cycle Analytics"
msgstr "週期分析簡介"
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "最後 %d 天"
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Update"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "最多顯示 %d 個事件"
@@ -81,28 +336,210 @@ msgstr[0] "最多顯示 %d 個事件"
msgid "Median"
msgstr "中位數"
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "新議題"
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+#, fuzzy
+msgid "New issue"
+msgstr "新議題"
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
msgid "Not available"
msgstr "不可用"
msgid "Not enough data"
msgstr "數據不足"
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
msgid "OpenedNDaysAgo|Opened"
msgstr "開始於"
+msgid "Owner"
+msgstr ""
+
msgid "Pipeline Health"
msgstr "流水線健康指標"
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project home"
+msgstr ""
+
+msgid "ProjectFeature|Disabled"
+msgstr ""
+
+msgid "ProjectFeature|Everyone with access"
+msgstr ""
+
+msgid "ProjectFeature|Only team members"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
msgid "ProjectLifecycle|Stage"
msgstr "項目生命週期"
+msgid "ProjectNetworkGraph|Graph"
+msgstr ""
+
msgid "Read more"
msgstr "了解更多"
+#, fuzzy
+msgid "Readme"
+msgstr "了解更多"
+
+msgid "RefSwitcher|Branches"
+msgstr ""
+
+msgid "RefSwitcher|Tags"
+msgstr ""
+
msgid "Related Commits"
msgstr "相關的提交"
@@ -121,67 +558,120 @@ msgstr "相關的合併請求"
msgid "Related Merged Requests"
msgstr "相關已合併的合並請求"
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}"
+msgstr ""
+
+msgid "Set up CI"
+msgstr ""
+
+msgid "Set up Koding"
+msgstr ""
+
+msgid "Set up auto deploy"
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
msgid "Showing %d event"
msgid_plural "Showing %d events"
msgstr[0] "顯示 %d 個事件"
-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."
+msgid "Source code"
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Target Branch"
+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 "編碼階段概述了從第一次提交到創建合併請求的時間。創建第壹個合並請求後,數據將自動添加到此處。"
msgid "The collection of events added to the data gathered for that stage."
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."
+msgid "The fork relationship has been removed."
+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 phase of the development lifecycle."
msgstr "項目生命週期中的各個階段。"
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first"
-" commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
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."
+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 "生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完成完整的想法到部署生產,數據將自動添加到此處。"
-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."
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+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 "評審階段概述了從創建合並請求到合併的時間。當創建第壹個合並請求後,數據將自動添加到此處。"
-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."
+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 "預發布階段概述了合並請求的合併到部署代碼到生產環境的總時間。當首次部署到生產環境後,數據將自動添加到此處。"
-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."
+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 "測試階段概述了GitLab CI為相關合併請求運行每個流水線所需的時間。當第壹個流水線運行完成後,數據將自動添加到此處。"
msgid "The time taken by each data entry gathered by that stage."
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."
+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 "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "議題被列入日程表的時間"
@@ -194,6 +684,135 @@ msgstr "從創建合併請求到被合並或關閉的時間"
msgid "Time until first merge request"
msgstr "創建第壹個合併請求之前的時間"
+#, fuzzy
+msgid "Timeago|%s days ago"
+msgstr "天"
+
+#, fuzzy
+msgid "Timeago|%s days remaining"
+msgstr "天"
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|1 day remaining"
+msgstr "天"
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|a day ago"
+msgstr "天"
+
+msgid "Timeago|a month ago"
+msgstr ""
+
+msgid "Timeago|a week ago"
+msgstr ""
+
+msgid "Timeago|a while"
+msgstr ""
+
+msgid "Timeago|a year ago"
+msgstr ""
+
+msgid "Timeago|about %s hours ago"
+msgstr ""
+
+msgid "Timeago|about a minute ago"
+msgstr ""
+
+msgid "Timeago|about an hour ago"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|in %s days"
+msgstr "天"
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|in 1 day"
+msgstr "天"
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|less than a minute ago"
+msgstr ""
+
msgid "Time|hr"
msgid_plural "Time|hrs"
msgstr[0] "小時"
@@ -211,15 +830,87 @@ msgstr "總時間"
msgid "Total test time for all commits/merges"
msgstr "所有提交和合併的總測試時間"
+msgid "Unstar"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權限不足。如需查看相關數據,請向管理員申請權限。"
msgid "We don't have enough data to show this stage."
msgstr "該階段的數據不足,無法顯示。"
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You must sign in to star a project"
+msgstr ""
+
msgid "You need permission."
msgstr "您需要相關的權限。"
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "committed"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "天"
+
+msgid "notification emails"
+msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 0caf35a915b..47d8b889b61 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -2,32 +2,188 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gitlab package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
+#
msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-05-04 19:24-0500\n"
"PO-Revision-Date: 2017-05-04 19:24-0500\n"
"Last-Translator: HuangTao <htve@outlook.com>, 2017\n"
-"Language-Team: Chinese (Taiwan) (https://www.transifex.com/gitlab-zh/teams/75177/zh_TW/)\n"
+"Language-Team: Chinese (Taiwan) (https://www.transifex.com/gitlab-zh/teams/751"
+"77/zh_TW/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_TW\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+msgid "About auto deploy"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add License"
+msgstr ""
+
+msgid "Add an SSH key to your profile to pull or push via SSH."
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Archived project! Repository is read-only"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Branch"
+msgid_plural "Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+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 ""
+
+msgid "Branches"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
+msgid "CI configuration"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "送交"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
+#, fuzzy
+msgid "CommitMessage|Add %{file_name}"
+msgstr "送交"
+
+#, fuzzy
+msgid "Commits"
+msgstr "送交"
+
+#, fuzzy
+msgid "Commits|History"
+msgstr "送交"
+
+msgid "Compare"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty bare repository"
+msgstr ""
+
+#, fuzzy
+msgid "Create merge request"
+msgstr "相關的合併請求"
+
+msgid "CreateNewFork|Fork"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+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 ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "週期分析概述了你的專案從想法到產品實現,各階段所需的時間。"
msgid "CycleAnalyticsStage|Code"
@@ -51,29 +207,128 @@ msgstr "預備"
msgid "CycleAnalyticsStage|Test"
msgstr "測試"
+msgid "Delete"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
+msgid "Description"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "首次推送"
msgid "FirstPushedBy|pushed by"
msgstr "推送者:"
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
msgid "From issue creation until deploy to production"
msgstr "從議題建立至線上部署"
msgid "From merge request merge until deploy to production"
msgstr "從請求被合併後至線上部署"
+msgid "Go to your fork"
+msgstr ""
+
+msgid "GoToYourFork|Fork"
+msgstr ""
+
+msgid "Home"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
msgid "Introducing Cycle Analytics"
msgstr "週期分析簡介"
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "最後 %d 天"
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Update"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "最多顯示 %d 個事件"
@@ -81,28 +336,210 @@ msgstr[0] "最多顯示 %d 個事件"
msgid "Median"
msgstr "中位數"
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "新議題"
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+#, fuzzy
+msgid "New issue"
+msgstr "新議題"
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
msgid "Not available"
msgstr "無法使用"
msgid "Not enough data"
msgstr "資料不足"
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
msgid "OpenedNDaysAgo|Opened"
msgstr "開始於"
+msgid "Owner"
+msgstr ""
+
msgid "Pipeline Health"
msgstr "流水線健康指標"
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project home"
+msgstr ""
+
+msgid "ProjectFeature|Disabled"
+msgstr ""
+
+msgid "ProjectFeature|Everyone with access"
+msgstr ""
+
+msgid "ProjectFeature|Only team members"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
msgid "ProjectLifecycle|Stage"
msgstr "專案生命週期"
+msgid "ProjectNetworkGraph|Graph"
+msgstr ""
+
msgid "Read more"
msgstr "了解更多"
+#, fuzzy
+msgid "Readme"
+msgstr "了解更多"
+
+msgid "RefSwitcher|Branches"
+msgstr ""
+
+msgid "RefSwitcher|Tags"
+msgstr ""
+
msgid "Related Commits"
msgstr "相關的送交"
@@ -121,67 +558,120 @@ msgstr "相關的合併請求"
msgid "Related Merged Requests"
msgstr "相關已合併的請求"
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}"
+msgstr ""
+
+msgid "Set up CI"
+msgstr ""
+
+msgid "Set up Koding"
+msgstr ""
+
+msgid "Set up auto deploy"
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
msgid "Showing %d event"
msgid_plural "Showing %d events"
msgstr[0] "顯示 %d 個事件"
-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."
+msgid "Source code"
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Target Branch"
+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 "程式開發階段顯示從第一次送交到建立合併請求的時間。建立第一個合併請求後,資料將自動填入。"
msgid "The collection of events added to the data gathered for that stage."
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."
+msgid "The fork relationship has been removed."
+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 phase of the development lifecycle."
msgstr "專案開發生命週期的各個階段。"
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first"
-" commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
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."
+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 "上線階段顯示從建立一個議題到部署程式至線上的總時間。當完成從想法到產品實現的循環後,資料將自動填入。"
-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."
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+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 "複閱階段顯示從合併請求建立後至被合併的時間。當建立第一個合併請求後,資料將自動填入。"
-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."
+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 "預備階段顯示從合併請求被合併後至部署上線的時間。當第一次部署上線後,資料將自動填入。"
-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."
+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 "測試階段顯示相關合併請求的流水線所花的時間。當第一個流水線運作完畢後,資料將自動填入。"
msgid "The time taken by each data entry gathered by that stage."
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."
+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 "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "議題被列入日程表的時間"
@@ -194,6 +684,135 @@ msgstr "合併請求被合併或是關閉的時間"
msgid "Time until first merge request"
msgstr "第一個合併請求被建立前的時間"
+#, fuzzy
+msgid "Timeago|%s days ago"
+msgstr "天"
+
+#, fuzzy
+msgid "Timeago|%s days remaining"
+msgstr "天"
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|1 day remaining"
+msgstr "天"
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|a day ago"
+msgstr "天"
+
+msgid "Timeago|a month ago"
+msgstr ""
+
+msgid "Timeago|a week ago"
+msgstr ""
+
+msgid "Timeago|a while"
+msgstr ""
+
+msgid "Timeago|a year ago"
+msgstr ""
+
+msgid "Timeago|about %s hours ago"
+msgstr ""
+
+msgid "Timeago|about a minute ago"
+msgstr ""
+
+msgid "Timeago|about an hour ago"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|in %s days"
+msgstr "天"
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+#, fuzzy
+msgid "Timeago|in 1 day"
+msgstr "天"
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|less than a minute ago"
+msgstr ""
+
msgid "Time|hr"
msgid_plural "Time|hrs"
msgstr[0] "小時"
@@ -211,15 +830,87 @@ msgstr "總時間"
msgid "Total test time for all commits/merges"
msgstr "所有送交和合併的總測試時間"
+msgid "Unstar"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權限不足。如需查看相關資料,請向管理員申請權限。"
msgid "We don't have enough data to show this stage."
msgstr "因該階段的資料不足而無法顯示相關資訊"
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You must sign in to star a project"
+msgstr ""
+
msgid "You need permission."
msgstr "您需要相關的權限。"
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "committed"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "天"
+
+msgid "notification emails"
+msgstr ""
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index 60db0192dfd..ed4ad7b600e 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -124,6 +124,13 @@ describe Groups::GroupMembersController do
expect(response).to redirect_to(dashboard_groups_path)
expect(group.users).not_to include user
end
+
+ it 'supports json request' do
+ delete :leave, group_id: group, format: :json
+
+ expect(response).to have_http_status(200)
+ expect(json_response['notice']).to eq "You left the \"#{group.name}\" group."
+ end
end
context 'and is an owner' do
diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb
index 130b0b744b5..bf1776eb320 100644
--- a/spec/controllers/projects/labels_controller_spec.rb
+++ b/spec/controllers/projects/labels_controller_spec.rb
@@ -117,7 +117,7 @@ describe Projects::LabelsController do
let!(:promoted_label_name) { "Promoted Label" }
let!(:label_1) { create(:label, title: promoted_label_name, project: project) }
- context 'not group owner' do
+ context 'not group reporters' do
it 'denies access' do
post :promote, namespace_id: project.namespace.to_param, project_id: project, id: label_1.to_param
@@ -125,9 +125,9 @@ describe Projects::LabelsController do
end
end
- context 'group owner' do
+ context 'group reporter' do
before do
- GroupMember.add_users(group, [user], :owner)
+ group.add_reporter(user)
end
it 'gives access' do
diff --git a/spec/features/dashboard/groups_list_spec.rb b/spec/features/dashboard/groups_list_spec.rb
index b0e2953dda2..7eb254f8451 100644
--- a/spec/features/dashboard/groups_list_spec.rb
+++ b/spec/features/dashboard/groups_list_spec.rb
@@ -6,40 +6,124 @@ describe 'Dashboard Groups page', js: true, feature: true do
let!(:nested_group) { create(:group, :nested) }
let!(:another_group) { create(:group) }
- before do
+ it 'shows groups user is member of' do
group.add_owner(user)
nested_group.add_owner(user)
login_as(user)
-
visit dashboard_groups_path
- end
- it 'shows groups user is member of' do
expect(page).to have_content(group.full_name)
expect(page).to have_content(nested_group.full_name)
expect(page).not_to have_content(another_group.full_name)
end
- it 'filters groups' do
- fill_in 'filter_groups', with: group.name
- wait_for_requests
+ describe 'when filtering groups' do
+ before do
+ group.add_owner(user)
+ nested_group.add_owner(user)
- expect(page).to have_content(group.full_name)
- expect(page).not_to have_content(nested_group.full_name)
- expect(page).not_to have_content(another_group.full_name)
+ login_as(user)
+
+ visit dashboard_groups_path
+ end
+
+ it 'filters groups' do
+ fill_in 'filter_groups', with: group.name
+ wait_for_requests
+
+ expect(page).to have_content(group.full_name)
+ expect(page).not_to have_content(nested_group.full_name)
+ expect(page).not_to have_content(another_group.full_name)
+ end
+
+ it 'resets search when user cleans the input' do
+ fill_in 'filter_groups', with: group.name
+ wait_for_requests
+
+ fill_in 'filter_groups', with: ""
+ wait_for_requests
+
+ expect(page).to have_content(group.full_name)
+ expect(page).to have_content(nested_group.full_name)
+ expect(page).not_to have_content(another_group.full_name)
+ expect(page.all('.js-groups-list-holder .content-list li').length).to eq 2
+ end
end
- it 'resets search when user cleans the input' do
- fill_in 'filter_groups', with: group.name
- wait_for_requests
+ describe 'group with subgroups' do
+ let!(:subgroup) { create(:group, :public, parent: group) }
- fill_in 'filter_groups', with: ""
- wait_for_requests
+ before do
+ group.add_owner(user)
+ subgroup.add_owner(user)
- expect(page).to have_content(group.full_name)
- expect(page).to have_content(nested_group.full_name)
- expect(page).not_to have_content(another_group.full_name)
- expect(page.all('.js-groups-list-holder .content-list li').length).to eq 2
+ login_as(user)
+
+ visit dashboard_groups_path
+ end
+
+ it 'shows subgroups inside of its parent group' do
+ expect(page).to have_selector('.groups-list-tree-container .group-list-tree', count: 2)
+ expect(page).to have_selector(".groups-list-tree-container #group-#{group.id} #group-#{subgroup.id}", count: 1)
+ end
+
+ it 'can toggle parent group' do
+ # Expanded by default
+ expect(page).to have_selector("#group-#{group.id} .fa-caret-down", count: 1)
+ expect(page).not_to have_selector("#group-#{group.id} .fa-caret-right")
+
+ # Collapse
+ find("#group-#{group.id}").trigger('click')
+
+ expect(page).not_to have_selector("#group-#{group.id} .fa-caret-down")
+ expect(page).to have_selector("#group-#{group.id} .fa-caret-right", count: 1)
+ expect(page).not_to have_selector("#group-#{group.id} #group-#{subgroup.id}")
+
+ # Expand
+ find("#group-#{group.id}").trigger('click')
+
+ expect(page).to have_selector("#group-#{group.id} .fa-caret-down", count: 1)
+ expect(page).not_to have_selector("#group-#{group.id} .fa-caret-right")
+ expect(page).to have_selector("#group-#{group.id} #group-#{subgroup.id}")
+ end
+ end
+
+ describe 'when using pagination' do
+ let(:group2) { create(:group) }
+
+ before do
+ group.add_owner(user)
+ group2.add_owner(user)
+
+ allow(Kaminari.config).to receive(:default_per_page).and_return(1)
+
+ login_as(user)
+ visit dashboard_groups_path
+ end
+
+ it 'shows pagination' do
+ expect(page).to have_selector('.gl-pagination')
+ expect(page).to have_selector('.gl-pagination .page', count: 2)
+ end
+
+ it 'loads results for next page' do
+ # Check first page
+ expect(page).to have_content(group2.full_name)
+ expect(page).to have_selector("#group-#{group2.id}")
+ expect(page).not_to have_content(group.full_name)
+ expect(page).not_to have_selector("#group-#{group.id}")
+
+ # Go to next page
+ find(".gl-pagination .page:not(.active) a").trigger('click')
+
+ wait_for_requests
+
+ # Check second page
+ expect(page).to have_content(group.full_name)
+ expect(page).to have_selector("#group-#{group.id}")
+ expect(page).not_to have_content(group2.full_name)
+ expect(page).not_to have_selector("#group-#{group2.id}")
+ end
end
end
diff --git a/spec/features/projects/group_links_spec.rb b/spec/features/projects/group_links_spec.rb
index 4e5682c8636..1b680a56492 100644
--- a/spec/features/projects/group_links_spec.rb
+++ b/spec/features/projects/group_links_spec.rb
@@ -16,15 +16,17 @@ feature 'Project group links', :feature, :js do
before do
visit namespace_project_settings_members_path(project.namespace, project)
+ click_on 'share-with-group-tab'
+
select2 group.id, from: '#link_group_id'
fill_in 'expires_at_groups', with: (Time.current + 4.5.days).strftime('%Y-%m-%d')
page.find('body').click
- click_on 'Share'
+ find('.btn-create').trigger('click')
end
it 'shows the expiration time with a warning class' do
- page.within('.enabled-groups') do
- expect(page).to have_content('expires in 4 days')
+ page.within('.project-members-groups') do
+ expect(page).to have_content('Expires in 4 days')
expect(page).to have_selector('.text-warning')
end
end
@@ -43,6 +45,7 @@ feature 'Project group links', :feature, :js do
it 'does not show ancestors', :nested_groups do
visit namespace_project_settings_members_path(project.namespace, project)
+ click_on 'share-with-group-tab'
click_link 'Search for a group'
page.within '.select2-drop' do
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index d3aebdecedd..49df91b236f 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -59,13 +59,13 @@ describe ApplicationHelper do
describe 'project_icon' do
it 'returns an url for the avatar' do
project = create(:empty_project, avatar: File.open(uploaded_image_temp_path))
- avatar_url = "/uploads/project/avatar/#{project.id}/banana_sample.gif"
+ avatar_url = "/uploads/system/project/avatar/#{project.id}/banana_sample.gif"
expect(helper.project_icon(project.full_path).to_s).
to eq "<img src=\"#{avatar_url}\" alt=\"Banana sample\" />"
allow(ActionController::Base).to receive(:asset_host).and_return(gitlab_host)
- avatar_url = "#{gitlab_host}/uploads/project/avatar/#{project.id}/banana_sample.gif"
+ avatar_url = "#{gitlab_host}/uploads/system/project/avatar/#{project.id}/banana_sample.gif"
expect(helper.project_icon(project.full_path).to_s).
to eq "<img src=\"#{avatar_url}\" alt=\"Banana sample\" />"
@@ -85,12 +85,12 @@ describe ApplicationHelper do
it 'returns an url for the avatar' do
user = create(:user, avatar: File.open(uploaded_image_temp_path))
- avatar_url = "/uploads/user/avatar/#{user.id}/banana_sample.gif"
+ avatar_url = "/uploads/system/user/avatar/#{user.id}/banana_sample.gif"
expect(helper.avatar_icon(user.email).to_s).to match(avatar_url)
allow(ActionController::Base).to receive(:asset_host).and_return(gitlab_host)
- avatar_url = "#{gitlab_host}/uploads/user/avatar/#{user.id}/banana_sample.gif"
+ avatar_url = "#{gitlab_host}/uploads/system/user/avatar/#{user.id}/banana_sample.gif"
expect(helper.avatar_icon(user.email).to_s).to match(avatar_url)
end
diff --git a/spec/javascripts/groups/group_item_spec.js b/spec/javascripts/groups/group_item_spec.js
new file mode 100644
index 00000000000..25e10552d95
--- /dev/null
+++ b/spec/javascripts/groups/group_item_spec.js
@@ -0,0 +1,102 @@
+import Vue from 'vue';
+import groupItemComponent from '~/groups/components/group_item.vue';
+import GroupsStore from '~/groups/stores/groups_store';
+import { group1 } from './mock_data';
+
+describe('Groups Component', () => {
+ let GroupItemComponent;
+ let component;
+ let store;
+ let group;
+
+ describe('group with default data', () => {
+ beforeEach((done) => {
+ GroupItemComponent = Vue.extend(groupItemComponent);
+ store = new GroupsStore();
+ group = store.decorateGroup(group1);
+
+ component = new GroupItemComponent({
+ propsData: {
+ group,
+ },
+ }).$mount();
+
+ Vue.nextTick(() => {
+ done();
+ });
+ });
+
+ afterEach(() => {
+ component.$destroy();
+ });
+
+ it('should render the group item correctly', () => {
+ expect(component.$el.classList.contains('group-row')).toBe(true);
+ expect(component.$el.classList.contains('.no-description')).toBe(false);
+ expect(component.$el.querySelector('.number-projects').textContent).toContain(group.numberProjects);
+ expect(component.$el.querySelector('.number-users').textContent).toContain(group.numberUsers);
+ expect(component.$el.querySelector('.group-visibility')).toBeDefined();
+ expect(component.$el.querySelector('.avatar-container')).toBeDefined();
+ expect(component.$el.querySelector('.title').textContent).toContain(group.name);
+ expect(component.$el.querySelector('.access-type').textContent).toContain(group.permissions.humanGroupAccess);
+ expect(component.$el.querySelector('.description').textContent).toContain(group.description);
+ expect(component.$el.querySelector('.edit-group')).toBeDefined();
+ expect(component.$el.querySelector('.leave-group')).toBeDefined();
+ });
+ });
+
+ describe('group without description', () => {
+ beforeEach((done) => {
+ GroupItemComponent = Vue.extend(groupItemComponent);
+ store = new GroupsStore();
+ group1.description = '';
+ group = store.decorateGroup(group1);
+
+ component = new GroupItemComponent({
+ propsData: {
+ group,
+ },
+ }).$mount();
+
+ Vue.nextTick(() => {
+ done();
+ });
+ });
+
+ afterEach(() => {
+ component.$destroy();
+ });
+
+ it('should render group item correctly', () => {
+ expect(component.$el.querySelector('.description').textContent).toBe('');
+ expect(component.$el.classList.contains('.no-description')).toBe(false);
+ });
+ });
+
+ describe('user has not access to group', () => {
+ beforeEach((done) => {
+ GroupItemComponent = Vue.extend(groupItemComponent);
+ store = new GroupsStore();
+ group1.permissions.human_group_access = null;
+ group = store.decorateGroup(group1);
+
+ component = new GroupItemComponent({
+ propsData: {
+ group,
+ },
+ }).$mount();
+
+ Vue.nextTick(() => {
+ done();
+ });
+ });
+
+ afterEach(() => {
+ component.$destroy();
+ });
+
+ it('should not display access type', () => {
+ expect(component.$el.querySelector('.access-type')).toBeNull();
+ });
+ });
+});
diff --git a/spec/javascripts/groups/groups_spec.js b/spec/javascripts/groups/groups_spec.js
new file mode 100644
index 00000000000..2a77f7259da
--- /dev/null
+++ b/spec/javascripts/groups/groups_spec.js
@@ -0,0 +1,64 @@
+import Vue from 'vue';
+import groupFolderComponent from '~/groups/components/group_folder.vue';
+import groupItemComponent from '~/groups/components/group_item.vue';
+import groupsComponent from '~/groups/components/groups.vue';
+import GroupsStore from '~/groups/stores/groups_store';
+import { groupsData } from './mock_data';
+
+describe('Groups Component', () => {
+ let GroupsComponent;
+ let store;
+ let component;
+ let groups;
+
+ beforeEach((done) => {
+ Vue.component('group-folder', groupFolderComponent);
+ Vue.component('group-item', groupItemComponent);
+
+ store = new GroupsStore();
+ groups = store.setGroups(groupsData.groups);
+
+ store.storePagination(groupsData.pagination);
+
+ GroupsComponent = Vue.extend(groupsComponent);
+
+ component = new GroupsComponent({
+ propsData: {
+ groups: store.state.groups,
+ pageInfo: store.state.pageInfo,
+ },
+ }).$mount();
+
+ Vue.nextTick(() => {
+ done();
+ });
+ });
+
+ afterEach(() => {
+ component.$destroy();
+ });
+
+ describe('with data', () => {
+ it('should render a list of groups', () => {
+ expect(component.$el.classList.contains('groups-list-tree-container')).toBe(true);
+ expect(component.$el.querySelector('#group-12')).toBeDefined();
+ expect(component.$el.querySelector('#group-1119')).toBeDefined();
+ expect(component.$el.querySelector('#group-1120')).toBeDefined();
+ });
+
+ it('should render group and its subgroup', () => {
+ const lists = component.$el.querySelectorAll('.group-list-tree');
+
+ expect(lists.length).toBe(3); // one parent and two subgroups
+
+ expect(lists[0].querySelector('#group-1119').classList.contains('is-open')).toBe(true);
+ expect(lists[0].querySelector('#group-1119').classList.contains('has-subgroups')).toBe(true);
+
+ expect(lists[2].querySelector('#group-1120').textContent).toContain(groups[1119].subGroups[1120].name);
+ });
+
+ it('should remove prefix of parent group', () => {
+ expect(component.$el.querySelector('#group-12 #group-1128 .title').textContent).toContain('level2 / level3 / level4');
+ });
+ });
+});
diff --git a/spec/javascripts/groups/mock_data.js b/spec/javascripts/groups/mock_data.js
new file mode 100644
index 00000000000..1c0ec7a97d0
--- /dev/null
+++ b/spec/javascripts/groups/mock_data.js
@@ -0,0 +1,110 @@
+const group1 = {
+ id: '12',
+ name: 'level1',
+ path: 'level1',
+ description: 'foo',
+ visibility: 'public',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/groups/level1',
+ full_name: 'level1',
+ full_path: 'level1',
+ parent_id: null,
+ created_at: '2017-05-15T19:01:23.670Z',
+ updated_at: '2017-05-15T19:01:23.670Z',
+ number_projects_with_delimiter: '1',
+ number_users_with_delimiter: '1',
+ has_subgroups: true,
+ permissions: {
+ human_group_access: 'Master',
+ },
+};
+
+// This group has no direct parent, should be placed as subgroup of group1
+const group14 = {
+ id: 1128,
+ name: 'level4',
+ path: 'level4',
+ description: 'foo',
+ visibility: 'public',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/groups/level1/level2/level3/level4',
+ full_name: 'level1 / level2 / level3 / level4',
+ full_path: 'level1/level2/level3/level4',
+ parent_id: 1127,
+ created_at: '2017-05-15T19:02:01.645Z',
+ updated_at: '2017-05-15T19:02:01.645Z',
+ number_projects_with_delimiter: '1',
+ number_users_with_delimiter: '1',
+ has_subgroups: true,
+ permissions: {
+ human_group_access: 'Master',
+ },
+};
+
+const group2 = {
+ id: 1119,
+ name: 'devops',
+ path: 'devops',
+ description: 'foo',
+ visibility: 'public',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/groups/devops',
+ full_name: 'devops',
+ full_path: 'devops',
+ parent_id: null,
+ created_at: '2017-05-11T19:35:09.635Z',
+ updated_at: '2017-05-11T19:35:09.635Z',
+ number_projects_with_delimiter: '1',
+ number_users_with_delimiter: '1',
+ has_subgroups: true,
+ permissions: {
+ human_group_access: 'Master',
+ },
+};
+
+const group21 = {
+ id: 1120,
+ name: 'chef',
+ path: 'chef',
+ description: 'foo',
+ visibility: 'public',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/groups/devops/chef',
+ full_name: 'devops / chef',
+ full_path: 'devops/chef',
+ parent_id: 1119,
+ created_at: '2017-05-11T19:51:04.060Z',
+ updated_at: '2017-05-11T19:51:04.060Z',
+ number_projects_with_delimiter: '1',
+ number_users_with_delimiter: '1',
+ has_subgroups: true,
+ permissions: {
+ human_group_access: 'Master',
+ },
+};
+
+const groupsData = {
+ groups: [group1, group14, group2, group21],
+ pagination: {
+ Date: 'Mon, 22 May 2017 22:31:52 GMT',
+ 'X-Prev-Page': '1',
+ 'X-Content-Type-Options': 'nosniff',
+ 'X-Total': '31',
+ 'Transfer-Encoding': 'chunked',
+ 'X-Runtime': '0.611144',
+ 'X-Xss-Protection': '1; mode=block',
+ 'X-Request-Id': 'f5db8368-3ce5-4aa4-89d2-a125d9dead09',
+ 'X-Ua-Compatible': 'IE=edge',
+ 'X-Per-Page': '20',
+ Link: '<http://localhost:3000/dashboard/groups.json?page=1&per_page=20>; rel="prev", <http://localhost:3000/dashboard/groups.json?page=1&per_page=20>; rel="first", <http://localhost:3000/dashboard/groups.json?page=2&per_page=20>; rel="last"',
+ 'X-Next-Page': '',
+ Etag: 'W/"a82f846947136271cdb7d55d19ef33d2"',
+ 'X-Frame-Options': 'DENY',
+ 'Content-Type': 'application/json; charset=utf-8',
+ 'Cache-Control': 'max-age=0, private, must-revalidate',
+ 'X-Total-Pages': '2',
+ 'X-Page': '2',
+ },
+};
+
+export { groupsData, group1 };
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index e3938a77680..52cf217c25f 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -150,6 +150,14 @@ import '~/lib/utils/common_utils';
const value = gl.utils.getParameterByName('fakeParameter');
expect(value).toBe(null);
});
+
+ it('should return valid paramentes if URL is provided', () => {
+ let value = gl.utils.getParameterByName('foo', 'http://cocteau.twins/?foo=bar');
+ expect(value).toBe('bar');
+
+ value = gl.utils.getParameterByName('manan', 'http://cocteau.twins/?foo=bar&manan=canchu');
+ expect(value).toBe('canchu');
+ });
});
describe('gl.utils.normalizedHeaders', () => {
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index 13827a26571..2c34402576b 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -51,7 +51,6 @@ if (process.env.BABEL_ENV === 'coverage') {
'./environments/environments_bundle.js',
'./filtered_search/filtered_search_bundle.js',
'./graphs/graphs_bundle.js',
- './issuable/issuable_bundle.js',
'./issuable/time_tracking/time_tracking_bundle.js',
'./main.js',
'./merge_conflicts/merge_conflicts_bundle.js',
diff --git a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
index f2bc15d39d7..d81774c8b8f 100644
--- a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
+++ b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
@@ -5,15 +5,7 @@ describe Gitlab::Diff::FileCollection::MergeRequestDiff do
let(:diff_files) { described_class.new(merge_request.merge_request_diff, diff_options: nil).diff_files }
it 'does not highlight binary files' do
- allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(double("text?" => false))
-
- expect_any_instance_of(Gitlab::Diff::File).not_to receive(:highlighted_diff_lines)
-
- diff_files
- end
-
- it 'does not highlight file if blob is not accessable' do
- allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(nil)
+ allow_any_instance_of(Gitlab::Diff::File).to receive(:text?).and_return(false)
expect_any_instance_of(Gitlab::Diff::File).not_to receive(:highlighted_diff_lines)
@@ -21,7 +13,7 @@ describe Gitlab::Diff::FileCollection::MergeRequestDiff do
end
it 'does not files marked as undiffable in .gitattributes' do
- allow_any_instance_of(Repository).to receive(:diffable?).and_return(false)
+ allow_any_instance_of(Gitlab::Diff::File).to receive(:diffable?).and_return(false)
expect_any_instance_of(Gitlab::Diff::File).not_to receive(:highlighted_diff_lines)
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index 050689b7c9a..a9953bb0d01 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::Diff::File, lib: true do
let(:project) { create(:project, :repository) }
let(:commit) { project.commit(sample_commit.id) }
let(:diff) { commit.raw_diffs.first }
- let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
+ let(:diff_file) { described_class.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
describe '#diff_lines' do
let(:diff_lines) { diff_file.diff_lines }
@@ -63,11 +63,33 @@ describe Gitlab::Diff::File, lib: true do
end
end
- describe '#blob' do
+ describe '#new_blob' do
it 'returns blob of new commit' do
- data = diff_file.blob.data
+ data = diff_file.new_blob.data
expect(data).to include('raise RuntimeError, "System commands must be given as an array of strings"')
end
end
+
+ describe '#diffable?' do
+ let(:commit) { project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863') }
+ let(:diffs) { commit.diffs }
+
+ before do
+ info_dir_path = File.join(project.repository.path_to_repo, 'info')
+
+ FileUtils.mkdir(info_dir_path) unless File.exist?(info_dir_path)
+ File.write(File.join(info_dir_path, 'attributes'), "*.md -diff\n")
+ end
+
+ it "returns true for files that do not have attributes" do
+ diff_file = diffs.diff_file_with_new_path('LICENSE')
+ expect(diff_file.diffable?).to be_truthy
+ end
+
+ it "returns false for files that have been marked as not being diffable in attributes" do
+ diff_file = diffs.diff_file_with_new_path('README.md')
+ expect(diff_file.diffable?).to be_falsey
+ end
+ end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 26215381cc4..e1e4aa9fde9 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1235,47 +1235,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- describe '#diffable' do
- info_dir_path = attributes_path = File.join(SEED_STORAGE_PATH, TEST_REPO_PATH, 'info')
- attributes_path = File.join(info_dir_path, 'attributes')
-
- before(:all) do
- FileUtils.mkdir(info_dir_path) unless File.exist?(info_dir_path)
- File.write(attributes_path, "*.md -diff\n")
- end
-
- it "should return true for files which are text and do not have attributes" do
- blob = Gitlab::Git::Blob.find(
- repository,
- '33bcff41c232a11727ac6d660bd4b0c2ba86d63d',
- 'LICENSE'
- )
- expect(repository.diffable?(blob)).to be_truthy
- end
-
- it "should return false for binary files which do not have attributes" do
- blob = Gitlab::Git::Blob.find(
- repository,
- '33bcff41c232a11727ac6d660bd4b0c2ba86d63d',
- 'files/images/logo-white.png'
- )
- expect(repository.diffable?(blob)).to be_falsey
- end
-
- it "should return false for text files which have been marked as not being diffable in attributes" do
- blob = Gitlab::Git::Blob.find(
- repository,
- '33bcff41c232a11727ac6d660bd4b0c2ba86d63d',
- 'README.md'
- )
- expect(repository.diffable?(blob)).to be_falsey
- end
-
- after(:all) do
- FileUtils.rm_rf(info_dir_path)
- end
- end
-
describe '#tag_exists?' do
it 'returns true for an existing tag' do
tag = repository.tag_names.first
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index a20cef3b000..c2bb9f9a166 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -7,30 +7,6 @@ describe Gitlab::Highlight, lib: true do
let(:repository) { project.repository }
let(:commit) { project.commit(sample_commit.id) }
- describe '.highlight_lines' do
- let(:lines) do
- Gitlab::Highlight.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb')
- end
-
- it 'highlights all the lines properly' do
- expect(lines[4]).to eq(%Q{<span id="LC5" class="line" lang="ruby"> <span class="kp">extend</span> <span class="nb">self</span></span>\n})
- expect(lines[21]).to eq(%Q{<span id="LC22" class="line" lang="ruby"> <span class="k">unless</span> <span class="no">File</span><span class="p">.</span><span class="nf">directory?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>\n})
- expect(lines[26]).to eq(%Q{<span id="LC27" class="line" lang="ruby"> <span class="vi">@cmd_status</span> <span class="o">=</span> <span class="mi">0</span></span>\n})
- end
-
- describe 'with CRLF' do
- let(:branch) { 'crlf-diff' }
- let(:blob) { repository.blob_at_branch(branch, path) }
- let(:lines) do
- Gitlab::Highlight.highlight_lines(project.repository, 'crlf-diff', 'files/whitespace')
- end
-
- it 'strips extra LFs' do
- expect(lines[0]).to eq("<span id=\"LC1\" class=\"line\" lang=\"plaintext\">test </span>")
- end
- end
- end
-
describe 'custom highlighting from .gitattributes' do
let(:branch) { 'gitattributes' }
let(:blob) { repository.blob_at_branch(branch, path) }
@@ -59,6 +35,19 @@ describe Gitlab::Highlight, lib: true do
end
describe '#highlight' do
+ describe 'with CRLF' do
+ let(:branch) { 'crlf-diff' }
+ let(:path) { 'files/whitespace' }
+ let(:blob) { repository.blob_at_branch(branch, path) }
+ let(:lines) do
+ Gitlab::Highlight.highlight(blob.path, blob.data, repository: repository).lines
+ end
+
+ it 'strips extra LFs' do
+ expect(lines[0]).to eq("<span id=\"LC1\" class=\"line\" lang=\"plaintext\">test </span>")
+ end
+ end
+
it 'links dependencies via DependencyLinker' do
expect(Gitlab::DependencyLinker).to receive(:link).
with('file.name', 'Contents', anything).and_call_original
diff --git a/spec/migrations/rename_system_namespaces_spec.rb b/spec/migrations/rename_system_namespaces_spec.rb
index ad1b83d8e2e..626a6005838 100644
--- a/spec/migrations/rename_system_namespaces_spec.rb
+++ b/spec/migrations/rename_system_namespaces_spec.rb
@@ -79,7 +79,9 @@ describe RenameSystemNamespaces, truncate: true do
it "moves the the repository for a project in the namespace" do
project = build(:project, namespace: system_namespace, path: "system-project")
save_invalid_routable(project)
- TestEnv.copy_repo(project)
+ TestEnv.copy_repo(project,
+ bare_repo: TestEnv.factory_repo_path_bare,
+ refs: TestEnv::BRANCH_SHA)
expected_repo = File.join(TestEnv.repos_path, "system0", "system-project.git")
migration.up
@@ -230,10 +232,10 @@ describe RenameSystemNamespaces, truncate: true do
describe "#child_ids_for_parent" do
it "collects child ids for all levels" do
- parent = create(:namespace)
- first_child = create(:namespace, parent: parent)
- second_child = create(:namespace, parent: parent)
- third_child = create(:namespace, parent: second_child)
+ parent = create(:group)
+ first_child = create(:group, parent: parent)
+ second_child = create(:group, parent: parent)
+ third_child = create(:group, parent: second_child)
all_ids = [parent.id, first_child.id, second_child.id, third_child.id]
collected_ids = migration.child_ids_for_parent(parent, ids: [parent.id])
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index f19e1af65a6..e1193e0d19a 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -199,6 +199,14 @@ describe Blob do
end
end
+ describe '#file_type' do
+ it 'returns the file type' do
+ blob = fake_blob(path: 'README.md')
+
+ expect(blob.file_type).to eq(:readme)
+ end
+ end
+
describe '#simple_viewer' do
context 'when the blob is empty' do
it 'returns an empty viewer' do
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 72f83d63224..140fd2720bf 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -67,11 +67,11 @@ describe Commit, models: true do
expect(commit.title).to eq("--no commit message")
end
- it "truncates a message without a newline at 80 characters" do
+ it 'truncates a message without a newline at natural break to 80 characters' do
message = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. Vivamus egestas lacinia lacus, sed rutrum mauris.'
allow(commit).to receive(:safe_message).and_return(message)
- expect(commit.title).to eq("#{message[0..79]}…")
+ expect(commit.title).to eq('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis…')
end
it "truncates a message with a newline before 80 characters at the newline" do
@@ -113,6 +113,28 @@ eos
end
end
+ describe 'description' do
+ it 'returns description of commit message if title less than 100 characters' do
+ message = <<eos
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit.
+Vivamus egestas lacinia lacus, sed rutrum mauris.
+eos
+
+ allow(commit).to receive(:safe_message).and_return(message)
+ expect(commit.description).to eq('Vivamus egestas lacinia lacus, sed rutrum mauris.')
+ end
+
+ it 'returns full commit message if commit title more than 100 characters' do
+ message = <<eos
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. Vivamus egestas lacinia lacus, sed rutrum mauris.
+Vivamus egestas lacinia lacus, sed rutrum mauris.
+eos
+
+ allow(commit).to receive(:safe_message).and_return(message)
+ expect(commit.description).to eq(message)
+ end
+ end
+
describe "delegation" do
subject { commit }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 316bf153660..3d437ca0fcc 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -179,7 +179,7 @@ describe Group, models: true do
let!(:group) { create(:group, :access_requestable, :with_avatar) }
let(:user) { create(:user) }
let(:gitlab_host) { "http://#{Gitlab.config.gitlab.host}" }
- let(:avatar_path) { "/uploads/group/avatar/#{group.id}/dk.png" }
+ let(:avatar_path) { "/uploads/system/group/avatar/#{group.id}/dk.png" }
context 'when avatar file is uploaded' do
before { group.add_master(user) }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 3ed52d42f86..454eeb58ecd 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -812,7 +812,7 @@ describe Project, models: true do
context 'when avatar file is uploaded' do
let(:project) { create(:empty_project, :with_avatar) }
- let(:avatar_path) { "/uploads/project/avatar/#{project.id}/dk.png" }
+ let(:avatar_path) { "/uploads/system/project/avatar/#{project.id}/dk.png" }
let(:gitlab_host) { "http://#{Gitlab.config.gitlab.host}" }
it 'shows correct url' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index a83726b48a0..d5bd9946ab6 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -987,7 +987,7 @@ describe User, models: true do
context 'when avatar file is uploaded' do
let(:gitlab_host) { "http://#{Gitlab.config.gitlab.host}" }
- let(:avatar_path) { "/uploads/user/avatar/#{user.id}/dk.png" }
+ let(:avatar_path) { "/uploads/system/user/avatar/#{user.id}/dk.png" }
it 'shows correct avatar url' do
expect(user.avatar_url).to eq(avatar_path)
diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb
index e1771b636b8..ddbed5f781e 100644
--- a/spec/policies/project_snippet_policy_spec.rb
+++ b/spec/policies/project_snippet_policy_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe ProjectSnippetPolicy, models: true do
let(:regular_user) { create(:user) }
let(:external_user) { create(:user, :external) }
- let(:project) { create(:empty_project) }
+ let(:project) { create(:empty_project, :public) }
let(:author_permissions) do
[
@@ -107,7 +107,7 @@ describe ProjectSnippetPolicy, models: true do
end
context 'snippet author' do
- let(:snippet) { create(:project_snippet, :private, author: regular_user) }
+ let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) }
subject { described_class.abilities(regular_user, snippet).to_set }
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index f018b48ceb2..c09be0ce1b9 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -648,7 +648,7 @@ describe 'Git HTTP requests', lib: true do
# Provide a dummy file in its place
allow_any_instance_of(Repository).to receive(:blob_at).and_call_original
allow_any_instance_of(Repository).to receive(:blob_at).with('b83d6e391c22777fca1ed3012fce84f633d7fed0', 'info/refs') do
- Gitlab::Git::Blob.find(project.repository, 'master', 'bar/branch-test.txt')
+ Blob.decorate(Gitlab::Git::Blob.find(project.repository, 'master', 'bar/branch-test.txt'), project)
end
get "/#{project.path_with_namespace}/blob/master/info/refs"
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index 05176c3beaa..6d1f0b24196 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -79,7 +79,7 @@ describe 'OpenID Connect requests' do
'email_verified' => true,
'website' => 'https://example.com',
'profile' => 'http://localhost/alice',
- 'picture' => "http://localhost/uploads/user/avatar/#{user.id}/dk.png"
+ 'picture' => "http://localhost/uploads/system/user/avatar/#{user.id}/dk.png"
})
end
end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index e9c2b865b47..77c07b71c68 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -38,6 +38,14 @@ describe Ci::CreatePipelineService, :services do
expect(pipeline.builds.first).to be_kind_of(Ci::Build)
end
+ it 'increments the prometheus counter' do
+ expect(Gitlab::Metrics).to receive(:counter)
+ .with(:pipelines_created_count, "Pipelines created count")
+ .and_call_original
+
+ pipeline
+ end
+
context 'when merge requests already exist for this source branch' do
it 'updates head pipeline of each merge request' do
merge_request_1 = create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project)
diff --git a/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb b/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb
index 935f4710851..bb46e1dd9ab 100644
--- a/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb
+++ b/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb
@@ -10,8 +10,8 @@ describe MergeRequests::MergeRequestDiffCacheService do
expect(Rails.cache).to receive(:read).with(cache_key).and_return({})
expect(Rails.cache).to receive(:write).with(cache_key, anything)
- allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(double("text?" => true))
- allow_any_instance_of(Repository).to receive(:diffable?).and_return(true)
+ allow_any_instance_of(Gitlab::Diff::File).to receive(:text?).and_return(true)
+ allow_any_instance_of(Gitlab::Diff::File).to receive(:diffable?).and_return(true)
subject.execute(merge_request)
end
diff --git a/spec/services/projects/participants_service_spec.rb b/spec/services/projects/participants_service_spec.rb
index 0657b7e93fe..d75851134ee 100644
--- a/spec/services/projects/participants_service_spec.rb
+++ b/spec/services/projects/participants_service_spec.rb
@@ -13,7 +13,7 @@ describe Projects::ParticipantsService, services: true do
groups = participants.groups
expect(groups.size).to eq 1
- expect(groups.first[:avatar_url]).to eq("/uploads/group/avatar/#{group.id}/dk.png")
+ expect(groups.first[:avatar_url]).to eq("/uploads/system/group/avatar/#{group.id}/dk.png")
end
it 'should return an url for the avatar with relative url' do
@@ -24,7 +24,7 @@ describe Projects::ParticipantsService, services: true do
groups = participants.groups
expect(groups.size).to eq 1
- expect(groups.first[:avatar_url]).to eq("/gitlab/uploads/group/avatar/#{group.id}/dk.png")
+ expect(groups.first[:avatar_url]).to eq("/gitlab/uploads/system/group/avatar/#{group.id}/dk.png")
end
end
end
diff --git a/spec/unicorn/unicorn_spec.rb b/spec/unicorn/unicorn_spec.rb
index 8518c047a47..41de94d35c2 100644
--- a/spec/unicorn/unicorn_spec.rb
+++ b/spec/unicorn/unicorn_spec.rb
@@ -67,8 +67,8 @@ describe 'Unicorn' do
end
def wait_unicorn_boot!(master_pid, ready_file)
- # Unicorn should boot in under 60 seconds so 120 seconds seems like a good timeout.
- timeout = 120
+ # We have seen the boot timeout after 2 minutes in CI so let's set it to 5 minutes.
+ timeout = 5 * 60
timeout.times do
return if File.exist?(ready_file)
pid = Process.waitpid(master_pid, Process::WNOHANG)