Commit 6e3e2cb0 authored by Nick Thomas's avatar Nick Thomas

Merge branch 'mw-i18n-app-models' into 'master'

Externalize strings in app/models

See merge request gitlab-org/gitlab-ce!27207
parents f9cf04fe cd6f7740
......@@ -198,7 +198,7 @@ class ApplicationSetting < ApplicationRecord
validates_each :restricted_visibility_levels do |record, attr, value|
value&.each do |level|
unless Gitlab::VisibilityLevel.options.value?(level)
record.errors.add(attr, "'#{level}' is not a valid visibility level")
record.errors.add(attr, _("'%{level}' is not a valid visibility level") % { level: level })
end
end
end
......@@ -206,7 +206,7 @@ class ApplicationSetting < ApplicationRecord
validates_each :import_sources do |record, attr, value|
value&.each do |source|
unless Gitlab::ImportSources.options.value?(source)
record.errors.add(attr, "'#{source}' is not a import source")
record.errors.add(attr, _("'%{source}' is not a import source") % { source: source })
end
end
end
......
......@@ -22,7 +22,7 @@ module GroupDescendant
return [] if descendants.empty?
unless descendants.all? { |hierarchy| hierarchy.is_a?(GroupDescendant) }
raise ArgumentError.new('element is not a hierarchy')
raise ArgumentError.new(_('element is not a hierarchy'))
end
all_hierarchies = descendants.map do |descendant|
......@@ -56,7 +56,7 @@ module GroupDescendant
end
if parent.nil? && hierarchy_top.present?
raise ArgumentError.new('specified top is not part of the tree')
raise ArgumentError.new(_('specified top is not part of the tree'))
end
if parent && parent != hierarchy_top
......
......@@ -41,7 +41,7 @@ module TokenAuthenticatableStrategies
def self.fabricate(model, field, options)
if options[:digest] && options[:encrypted]
raise ArgumentError, 'Incompatible options set!'
raise ArgumentError, _('Incompatible options set!')
end
if options[:digest]
......
......@@ -13,7 +13,7 @@ module TokenAuthenticatableStrategies
elsif migrating?
find_by_plaintext_token(token, unscoped)
else
raise ArgumentError, "Unknown encryption strategy: #{encrypted_strategy}!"
raise ArgumentError, _("Unknown encryption strategy: %{encrypted_strategy}!") % { encrypted_strategy: encrypted_strategy }
end
end
......@@ -32,7 +32,7 @@ module TokenAuthenticatableStrategies
return super if instance.has_attribute?(encrypted_field)
if required?
raise ArgumentError, 'Using required encryption strategy when encrypted field is missing!'
raise ArgumentError, _('Using required encryption strategy when encrypted field is missing!')
else
insecure_strategy.ensure_token(instance)
end
......@@ -74,7 +74,7 @@ module TokenAuthenticatableStrategies
value = value.call if value.is_a?(Proc)
unless value.in?([:required, :optional, :migrating])
raise ArgumentError, 'encrypted: needs to be a :required, :optional or :migrating!'
raise ArgumentError, _('encrypted: needs to be a :required, :optional or :migrating!')
end
value
......
......@@ -291,22 +291,22 @@ class Milestone < ApplicationRecord
end
title_exists = relation.find_by_title(title)
errors.add(:title, "already being used for another group or project milestone.") if title_exists
errors.add(:title, _("already being used for another group or project milestone.")) if title_exists
end
# Milestone should be either a project milestone or a group milestone
def milestone_type_check
if group_id && project_id
field = project_id_changed? ? :project_id : :group_id
errors.add(field, "milestone should belong either to a project or a group.")
errors.add(field, _("milestone should belong either to a project or a group."))
end
end
def milestone_format_reference(format = :iid)
raise ArgumentError, 'Unknown format' unless [:iid, :name].include?(format)
raise ArgumentError, _('Unknown format') unless [:iid, :name].include?(format)
if group_milestone? && format == :iid
raise ArgumentError, 'Cannot refer to a group milestone by an internal id!'
raise ArgumentError, _('Cannot refer to a group milestone by an internal id!')
end
if format == :name && !name.include?('"')
......@@ -322,7 +322,7 @@ class Milestone < ApplicationRecord
def start_date_should_be_less_than_due_date
if due_date <= start_date
errors.add(:due_date, "must be greater than start date")
errors.add(:due_date, _("must be greater than start date"))
end
end
......
......@@ -313,7 +313,7 @@ class Project < ApplicationRecord
validates :description, length: { maximum: 2000 }, allow_blank: true
validates :ci_config_path,
format: { without: %r{(\.{2}|\A/)},
message: 'cannot include leading slash or directory traversal.' },
message: _('cannot include leading slash or directory traversal.') },
length: { maximum: 255 },
allow_blank: true
validates :name,
......@@ -420,13 +420,13 @@ class Project < ApplicationRecord
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
default: 3600, error_message: 'Maximum job timeout has a value which could not be accepted'
default: 3600, error_message: _('Maximum job timeout has a value which could not be accepted')
validates :build_timeout, allow_nil: true,
numericality: { greater_than_or_equal_to: 10.minutes,
less_than: 1.month,
only_integer: true,
message: 'needs to be beetween 10 minutes and 1 month' }
message: _('needs to be beetween 10 minutes and 1 month') }
# Used by Projects::CleanupService to hold a map of rewritten object IDs
mount_uploader :bfg_object_map, AttachmentUploader
......@@ -850,7 +850,7 @@ class Project < ApplicationRecord
def mark_stuck_remote_mirrors_as_failed!
remote_mirrors.stuck.update_all(
update_status: :failed,
last_error: 'The remote mirror took to long to complete.',
last_error: _('The remote mirror took to long to complete.'),
last_update_at: Time.now
)
end
......@@ -887,14 +887,14 @@ class Project < ApplicationRecord
level_name = Gitlab::VisibilityLevel.level_name(self.visibility_level).downcase
group_level_name = Gitlab::VisibilityLevel.level_name(self.group.visibility_level).downcase
self.errors.add(:visibility_level, "#{level_name} is not allowed in a #{group_level_name} group.")
self.errors.add(:visibility_level, _("%{level_name} is not allowed in a %{group_level_name} group.") % { level_name: level_name, group_level_name: group_level_name })
end
def visibility_level_allowed_as_fork
return if visibility_level_allowed_as_fork?
level_name = Gitlab::VisibilityLevel.level_name(self.visibility_level).downcase
self.errors.add(:visibility_level, "#{level_name} is not allowed since the fork source project has lower visibility.")
self.errors.add(:visibility_level, _("%{level_name} is not allowed since the fork source project has lower visibility.") % { level_name: level_name })
end
def check_wiki_path_conflict
......@@ -903,7 +903,7 @@ class Project < ApplicationRecord
path_to_check = path.ends_with?('.wiki') ? path.chomp('.wiki') : "#{path}.wiki"
if Project.where(namespace_id: namespace_id, path: path_to_check).exists?
errors.add(:name, 'has already been taken')
errors.add(:name, _('has already been taken'))
end
end
......@@ -923,7 +923,7 @@ class Project < ApplicationRecord
return unless pages_https_only?
unless pages_domains.all?(&:https?)
errors.add(:pages_https_only, "cannot be enabled unless all domains have TLS certificates")
errors.add(:pages_https_only, _("cannot be enabled unless all domains have TLS certificates"))
end
end
......@@ -1203,7 +1203,7 @@ class Project < ApplicationRecord
def valid_repo?
repository.exists?
rescue
errors.add(:path, 'Invalid repository path')
errors.add(:path, _('Invalid repository path'))
false
end
......@@ -1294,7 +1294,7 @@ class Project < ApplicationRecord
# Check if repository with same path already exists on disk we can
# skip this for the hashed storage because the path does not change
if legacy_storage? && repository_with_same_path_already_exists?
errors.add(:base, 'There is already a repository with that name on disk')
errors.add(:base, _('There is already a repository with that name on disk'))
return false
end
......@@ -1316,7 +1316,7 @@ class Project < ApplicationRecord
repository.after_create
true
else
errors.add(:base, 'Failed to create repository via gitlab-shell')
errors.add(:base, _('Failed to create repository via gitlab-shell'))
false
end
end
......@@ -1392,7 +1392,7 @@ class Project < ApplicationRecord
ProjectCacheWorker.perform_async(self.id, [], [:commit_count])
reload_default_branch
else
errors.add(:base, "Could not change HEAD: branch '#{branch}' does not exist")
errors.add(:base, _("Could not change HEAD: branch '%{branch}' does not exist") % { branch: branch })
false
end
end
......@@ -1444,7 +1444,7 @@ class Project < ApplicationRecord
ProjectWiki.new(self, self.owner).wiki
true
rescue ProjectWiki::CouldNotCreateWikiError
errors.add(:base, 'Failed create wiki')
errors.add(:base, _('Failed create wiki'))
false
end
......@@ -1933,7 +1933,7 @@ class Project < ApplicationRecord
#
# @param [Symbol] feature that needs to be rolled out for the project (:repository, :attachments)
def hashed_storage?(feature)
raise ArgumentError, "Invalid feature" unless HASHED_STORAGE_FEATURES.include?(feature)
raise ArgumentError, _("Invalid feature") unless HASHED_STORAGE_FEATURES.include?(feature)
self.storage_version && self.storage_version >= HASHED_STORAGE_FEATURES[feature]
end
......@@ -2165,7 +2165,7 @@ class Project < ApplicationRecord
return if skip_disk_validation
if repository_storage.blank? || repository_with_same_path_already_exists?
errors.add(:base, 'There is already a repository with that name on disk')
errors.add(:base, _('There is already a repository with that name on disk'))
throw :abort
end
end
......@@ -2211,7 +2211,7 @@ class Project < ApplicationRecord
errors.delete(error)
end
errors.add(:base, "The project is still being deleted. Please try again later.")
errors.add(:base, _("The project is still being deleted. Please try again later."))
end
def pending_delete_twin
......
......@@ -14,7 +14,7 @@ class ProjectGroupLink < ApplicationRecord
validates :project_id, presence: true
validates :group, presence: true
validates :group_id, uniqueness: { scope: [:project_id], message: "already shared with this group" }
validates :group_id, uniqueness: { scope: [:project_id], message: _("already shared with this group") }
validates :group_access, presence: true
validates :group_access, inclusion: { in: Gitlab::Access.values }, presence: true
validate :different_group
......@@ -44,7 +44,7 @@ class ProjectGroupLink < ApplicationRecord
group_ids = project_group.ancestors.map(&:id).push(project_group.id)
if group_ids.include?(self.group.id)
errors.add(:base, "Project cannot be shared with the group it is in or one of its ancestors.")
errors.add(:base, _("Project cannot be shared with the group it is in or one of its ancestors."))
end
end
......
......@@ -11,7 +11,7 @@ class AsanaService < Service
end
def description
'Asana - Teamwork without email'
s_('AsanaService|Asana - Teamwork without email')
end
def help
......@@ -36,13 +36,13 @@ http://app.asana.com/-/account_api'
{
type: 'text',
name: 'api_key',
placeholder: 'User Personal Access Token. User must have access to task, all comments will be attributed to this user.',
placeholder: s_('AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user.'),
required: true
},
{
type: 'text',
name: 'restrict_to_branch',
placeholder: 'Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.'
placeholder: s_('AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.')
}
]
end
......@@ -73,7 +73,7 @@ http://app.asana.com/-/account_api'
project_name = project.full_name
data[:commits].each do |commit|
push_msg = "#{user} pushed to branch #{branch} of #{project_name} ( #{commit[:url]} ):"
push_msg = s_("AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):") % { user: user, branch: branch, project_name: project_name, commit_url: commit[:url] }
check_commit(commit[:message], push_msg)
end
end
......
......@@ -31,15 +31,15 @@ class BambooService < CiService
end
def title
'Atlassian Bamboo CI'
s_('BambooService|Atlassian Bamboo CI')
end
def description
'A continuous integration and build server'
s_('BambooService|A continuous integration and build server')
end
def help
'You must set up automatic revision labeling and a repository trigger in Bamboo.'
s_('BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo.')
end
def self.to_param
......@@ -49,11 +49,11 @@ class BambooService < CiService
def fields
[
{ type: 'text', name: 'bamboo_url',
placeholder: 'Bamboo root URL like https://bamboo.example.com', required: true },
placeholder: s_('BambooService|Bamboo root URL like https://bamboo.example.com'), required: true },
{ type: 'text', name: 'build_key',
placeholder: 'Bamboo build plan key like KEY', required: true },
placeholder: s_('BambooService|Bamboo build plan key like KEY'), required: true },
{ type: 'text', name: 'username',
placeholder: 'A user with API access, if applicable' },
placeholder: s_('BambooService|A user with API access, if applicable') },
{ type: 'password', name: 'password' }
]
end
......
......@@ -4,11 +4,11 @@ require "discordrb/webhooks"
class DiscordService < ChatNotificationService
def title
"Discord Notifications"
s_("DiscordService|Discord Notifications")
end
def description
"Receive event notifications in Discord"
s_("DiscordService|Receive event notifications in Discord")
end
def self.to_param
......
......@@ -7,11 +7,11 @@ class EmailsOnPushService < Service
validates :recipients, presence: true, if: :valid_recipients?
def title
'Emails on push'
s_('EmailsOnPushService|Emails on push')
end
def description
'Email the commits and diff of each push to a list of recipients.'
s_('EmailsOnPushService|Email the commits and diff of each push to a list of recipients.')
end
def self.to_param
......@@ -45,11 +45,11 @@ class EmailsOnPushService < Service
def fields
domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ")
[
{ type: 'checkbox', name: 'send_from_committer_email', title: "Send from committer",
help: "Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. #{domains})." },
{ type: 'checkbox', name: 'disable_diffs', title: "Disable code diffs",
help: "Don't include possibly sensitive code diffs in notification body." },
{ type: 'textarea', name: 'recipients', placeholder: 'Emails separated by whitespace' }
{ type: 'checkbox', name: 'send_from_committer_email', title: s_("EmailsOnPushService|Send from committer"),
help: s_("EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains}).") % { domains: domains } },
{ type: 'checkbox', name: 'disable_diffs', title: s_("EmailsOnPushService|Disable code diffs"),
help: s_("EmailsOnPushService|Don't include possibly sensitive code diffs in notification body.") },
{ type: 'textarea', name: 'recipients', placeholder: s_('EmailsOnPushService|Emails separated by whitespace') }
]
end
end
......@@ -6,11 +6,11 @@ class ExternalWikiService < Service
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
def title
'External Wiki'
s_('ExternalWikiService|External Wiki')
end
def description
'Replaces the link to the internal wiki with a link to an external wiki.'
s_('ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki.')
end
def self.to_param
......@@ -19,7 +19,7 @@ class ExternalWikiService < Service
def fields
[
{ type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki', required: true }
{ type: 'text', name: 'external_wiki_url', placeholder: s_('ExternalWikiService|The URL of the external Wiki'), required: true }
]
end
......
......@@ -9,7 +9,7 @@ class FlowdockService < Service
end
def description
'Flowdock is a collaboration web app for technical teams.'
s_('FlowdockService|Flowdock is a collaboration web app for technical teams.')
end
def self.to_param
......@@ -18,7 +18,7 @@ class FlowdockService < Service
def fields
[
{ type: 'text', name: 'token', placeholder: 'Flowdock Git source token', required: true }
{ type: 'text', name: 'token', placeholder: s_('FlowdockService|Flowdock Git source token'), required: true }
]
end
......
......@@ -11,7 +11,7 @@ class JiraService < IssueTrackerService
validates :password, presence: true, if: :activated?
validates :jira_issue_transition_id,
format: { with: Gitlab::Regex.jira_transition_id_regex, message: "transition ids can have only numbers which can be split with , or ;" },
format: { with: Gitlab::Regex.jira_transition_id_regex, message: s_("JiraService|transition ids can have only numbers which can be split with , or ;") },
allow_blank: true
# JIRA cloud version is deprecating authentication via username and password.
......@@ -86,7 +86,7 @@ class JiraService < IssueTrackerService
if self.properties && self.properties['description'].present?
self.properties['description']
else
'Jira issue tracker'
s_('JiraService|Jira issue tracker')
end
end
......@@ -96,11 +96,11 @@ class JiraService < IssueTrackerService
def fields
[
{ type: 'text', name: 'url', title: 'Web URL', placeholder: 'https://jira.example.com', required: true },
{ type: 'text', name: 'api_url', title: 'JIRA API URL', placeholder: 'If different from Web URL' },
{ type: 'text', name: 'username', title: 'Username or Email', placeholder: 'Use a username for server version and an email for cloud version', required: true },
{ type: 'password', name: 'password', title: 'Password or API token', placeholder: 'Use a password for server version and an API token for cloud version', required: true },
{ type: 'text', name: 'jira_issue_transition_id', title: 'Transition ID(s)', placeholder: 'Use , or ; to separate multiple transition IDs' }
{ type: 'text', name: 'url', title: s_('JiraService|Web URL'), placeholder: 'https://jira.example.com', required: true },
{ type: 'text', name: 'api_url', title: s_('JiraService|JIRA API URL'), placeholder: s_('JiraService|If different from Web URL') },
{ type: 'text', name: 'username', title: s_('JiraService|Username or Email'), placeholder: s_('JiraService|Use a username for server version and an email for cloud version'), required: true },
{ type: 'password', name: 'password', title: s_('JiraService|Password or API token'), placeholder: s_('JiraService|Use a password for server version and an API token for cloud version'), required: true },
{ type: 'text', name: 'jira_issue_transition_id', title: s_('JiraService|Transition ID(s)'), placeholder: s_('JiraService|Use , or ; to separate multiple transition IDs') }
]
end
......@@ -139,7 +139,7 @@ class JiraService < IssueTrackerService
def create_cross_reference_note(mentioned, noteable, author)
unless can_cross_reference?(noteable)
return "Events for #{noteable.model_name.plural.humanize(capitalize: false)} are disabled."
return s_("JiraService|Events for %{noteable_model_name} are disabled.") % { noteable_model_name: noteable.model_name.plural.humanize(capitalize: false) }
end
jira_issue = jira_request { client.Issue.find(mentioned.id) }
......@@ -338,9 +338,9 @@ class JiraService < IssueTrackerService
def self.event_description(event)
case event
when "merge_request", "merge_request_events"
"JIRA comments will be created when an issue gets referenced in a merge request."
s_("JiraService|JIRA comments will be created when an issue gets referenced in a merge request.")
when "commit", "commit_events"
"JIRA comments will be created when an issue gets referenced in a commit."
s_("JiraService|JIRA comments will be created when an issue gets referenced in a commit.")
end
end
end
......@@ -10,11 +10,11 @@ class PipelinesEmailService < Service
end
def title
'Pipelines emails'
_('Pipelines emails')
end
def description
'Email the pipelines status to a list of recipients.'
_('Email the pipelines status to a list of recipients.')
end
def self.to_param
......@@ -51,7 +51,7 @@ class PipelinesEmailService < Service
[
{ type: 'textarea',
name: 'recipients',
placeholder: 'Emails separated by comma',
placeholder: _('Emails separated by comma'),
required: true },
{ type: 'checkbox',
name: 'notify_only_broken_pipelines' }
......
......@@ -11,7 +11,7 @@ class PivotaltrackerService < Service
end
def description
'Project Management Software (Source Commits Endpoint)'
s_('PivotalTrackerService|Project Management Software (Source Commits Endpoint)')
end
def self.to_param
......@@ -23,14 +23,14 @@ class PivotaltrackerService < Service
{
type: 'text',
name: 'token',
placeholder: 'Pivotal Tracker API token.',
placeholder: s_('PivotalTrackerService|Pivotal Tracker API token.'),
required: true
},
{
type: 'text',
name: 'restrict_to_branch',
placeholder: 'Comma-separated list of branches which will be ' \
'automatically inspected. Leave blank to include all branches.'
placeholder: s_('PivotalTrackerService|Comma-separated list of branches which will be ' \
'automatically inspected. Leave blank to include all branches.')
}
]
end
......
......@@ -11,7 +11,7 @@ class PushoverService < Service
end
def description
'Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop.'
s_('PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop.')
end
def self.to_param
......@@ -20,15 +20,15 @@ class PushoverService < Service
def fields
[
{ type: 'text', name: 'api_key', placeholder: 'Your application key', required: true },
{ type: 'text', name: 'user_key', placeholder: 'Your user key', required: true },
{ type: 'text', name: 'device', placeholder: 'Leave blank for all active devices' },
{ type: 'text', name: 'api_key', placeholder: s_('PushoverService|Your application key'), required: true },
{ type: 'text', name: 'user_key', placeholder: s_('PushoverService|Your user key'), required: true },
{ type: 'text', name: 'device', placeholder: s_('PushoverService|Leave blank for all active devices') },
{ type: 'select', name: 'priority', required: true, choices:
[
['Lowest Priority', -2],
['Low Priority', -1],
['Normal Priority', 0],
['High Priority', 1]
[s_('PushoverService|Lowest Priority'), -2],
[s_('PushoverService|Low Priority'), -1],
[s_('PushoverService|Normal Priority'), 0],
[s_('PushoverService|High Priority'), 1]
],
default_choice: 0 },
{ type: 'select', name: 'sound', choices:
......@@ -73,15 +73,15 @@ class PushoverService < Service
message =
if Gitlab::Git.blank_ref?(before)
"#{data[:user_name]} pushed new branch \"#{ref}\"."
s_("PushoverService|%{user_name} pushed new branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
elsif Gitlab::Git.blank_ref?(after)
"#{data[:user_name]} deleted branch \"#{ref}\"."
s_("PushoverService|%{user_name} deleted branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
else
"#{data[:user_name]} push to branch \"#{ref}\"."
s_("PushoverService|%{user_name} push to branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
end
if data[:total_commits_count] > 0
message = [message, "Total commits count: #{data[:total_commits_count]}"].join("\n")
message = [message, s_("PushoverService|Total commits count: %{total_commits_count}") % { total_commits_count: data[:total_commits_count] }].join("\n")
end
pushover_data = {
......@@ -92,7 +92,7 @@ class PushoverService < Service
title: "#{project.full_name}",
message: message,
url: data[:project][:web_url],
url_title: "See project #{project.full_name}"
url_title: s_("PushoverService|See project %{project_full_name}") % { project_full_name: project.full_name }
}
# Sound parameter MUST NOT be sent to API if not selected
......
......@@ -19,7 +19,7 @@ class U2fRegistration < ApplicationRecord
user: user,
name: params[:name])
rescue JSON::ParserError, NoMethodError, ArgumentError
registration.errors.add(:base, 'Your U2F device did not send a valid JSON response.')
registration.errors.add(:base, _('Your U2F device did not send a valid JSON response.'))
rescue U2F::Error => e
registration.errors.add(:base, e.message)
end
......
......@@ -45,7 +45,7 @@ class Upload < ApplicationRecord
end
def absolute_path
raise ObjectStorage::RemoteStoreError, "Remote object has no absolute path." unless local?
raise ObjectStorage::RemoteStoreError, _("Remote object has no absolute path.") unless local?
return path unless relative_path?
uploader_class.absolute_path(self)
......@@ -71,10 +71,10 @@ class Upload < ApplicationRecord
# Help sysadmins find missing upload files
if persisted? && !exist
if Gitlab::Sentry.enabled?
Raven.capture_message("Upload file does not exist", extra: self.attributes)
Raven.capture_message(_("Upload file does not exist"), extra: self.attributes)
end
Gitlab::Metrics.counter(:upload_file_does_not_exist_total, 'The number of times an upload record could not find its file').increment
Gitlab::Metrics.counter(:upload_file_does_not_exist_total, _('The number of times an upload record could not find its file')).increment
end
exist
......
......@@ -517,7 +517,7 @@ class User < ApplicationRecord
def ghost
email = 'ghost%s@example.com'
unique_internal(where(ghost: true), 'ghost', email) do |u|
u.bio = 'This is a "Ghost User", created to hold all issues authored by users that have since been deleted. This user cannot be removed.'
u.bio = _('This is a "Ghost User", created to hold all issues authored by users that have since been deleted. This user cannot be removed.')
u.name = 'Ghost User'
end
end
......@@ -622,32 +622,32 @@ class User < ApplicationRecord
def namespace_move_dir_allowed
if namespace&.any_project_has_container_registry_tags?
errors.add(:username, 'cannot be changed if a personal project has container registry tags.')
errors.add(:username, _('cannot be changed if a personal project has container registry tags.'))
end
end
def unique_email
if !emails.exists?(email: email) && Email.exists?(email: email)
errors.add(:email, 'has already been taken')
errors.add(:email, _('has already been taken'))
end
end
def owns_notification_email
return if temp_oauth_email?
errors.add(:notification_email, "is not an email you own") unless all_emails.include?(notification_email)
errors.add(:notification_email, _("is not an email you own")) unless all_emails.include?(notification_email)
end
def owns_public_email
return if public_email.blank?
errors.add(:public_email, "is not an email you own") unless all_emails.include?(public_email)
errors.add(:public_email, _("is not an email you own")) unless all_emails.include?(public_email)
end
def owns_commit_email
return if read_attribute(:commit_email).blank?
errors.add(:commit_email, "is not an email you own") unless verified_emails.include?(commit_email)
errors.add(:commit_email, _("is not an email you own")) unless verified_emails.include?(commit_email)
end
# Define commit_email-related attribute methods explicitly instead of relying
......
......@@ -132,6 +132,12 @@ msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{level_name} is not allowed in a %{group_level_name} group."
msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
......@@ -203,6 +209,12 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
msgstr ""
msgid "'%{source}' is not a import source"
msgstr ""
msgid "(external source)"
msgstr ""
......@@ -978,6 +990,18 @@ msgstr ""
msgid "Artifacts"
msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
msgid "AsanaService|Asana - Teamwork without email"
msgstr ""
msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
msgstr ""
msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
msgstr ""
msgid "Ask your group maintainer to set up a group Runner."
msgstr ""
......@@ -1221,6 +1245,24 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
msgid "BambooService|A continuous integration and build server"
msgstr ""
msgid "BambooService|A user with API access, if applicable"
msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
msgstr ""
msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
msgstr ""
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
......@@ -1515,6 +1557,9 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
......@@ -2600,6 +2645,9 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
msgid "Could not change HEAD: branch '%{branch}' does not exist"
msgstr ""
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
......@@ -3109,6 +3157,12 @@ msgstr ""
msgid "Discard draft"
msgstr ""
msgid "DiscordService|Discord Notifications"
msgstr ""
msgid "DiscordService|Receive event notifications in Discord"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
......@@ -3235,6 +3289,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
msgid "Email the pipelines status to a list of recipients."
msgstr ""
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
......@@ -3262,6 +3319,30 @@ msgstr ""
msgid "Emails"
msgstr ""
msgid "Emails separated by comma"
msgstr ""
msgid "EmailsOnPushService|Disable code diffs"
msgstr ""
msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
msgstr ""
msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
msgstr ""
msgid "EmailsOnPushService|Emails on push"
msgstr ""
msgid "EmailsOnPushService|Emails separated by whitespace"
msgstr ""
msgid "EmailsOnPushService|Send from committer"
msgstr ""
msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
msgstr ""
msgid "Embed"
msgstr ""
......@@ -3751,6 +3832,15 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
msgid "ExternalWikiService|External Wiki"
msgstr ""
msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
msgstr ""
msgid "ExternalWikiService|The URL of the external Wiki"
msgstr ""
msgid "Facebook"
msgstr ""
......@@ -3760,12 +3850,18 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
msgid "Failed create wiki"
msgstr ""
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
msgid "Failed to create repository via gitlab-shell"
msgstr ""
msgid "Failed to create resources"
msgstr ""
......@@ -3921,6 +4017,12 @@ msgstr ""
msgid "FirstPushedBy|pushed by"
msgstr ""
msgid "FlowdockService|Flowdock Git source token"
msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
msgid "FogBugz Email"
msgstr ""
......@@ -4607,6 +4709,9 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
msgid "Incompatible options set!"
msgstr ""
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
......@@ -4682,6 +4787,9 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
msgid "Invalid feature"
msgstr ""
msgid "Invalid file."
msgstr ""
......@@ -4691,6 +4799,9 @@ msgstr ""
msgid "Invalid pin code"
msgstr ""
msgid "Invalid repository path"
msgstr ""
msgid "Invalid two-factor code."
msgstr ""
......@@ -4751,6 +4862,48 @@ msgstr ""
msgid "January"
msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|JIRA API URL"
msgstr ""
msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
msgstr ""
msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
msgid "JiraService|Transition ID(s)"
msgstr ""
msgid "JiraService|Use , or ; to separate multiple transition IDs"
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
msgid "JiraService|Web URL"
msgstr ""
msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
msgstr ""
msgid "Job"
msgstr ""
......@@ -5187,6 +5340,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
......@@ -6133,6 +6289,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
msgid "Pipelines emails"
msgstr ""
msgid "Pipelines for last month"
msgstr ""
......@@ -6256,6 +6415,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
msgstr ""
msgid "PivotalTrackerService|Pivotal Tracker API token."
msgstr ""
msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
msgstr ""
msgid "Plain diff"
msgstr ""
......@@ -6667,6 +6835,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
msgid "Project cannot be shared with the group it is in or one of its ancestors."
msgstr ""
msgid "Project configuration, including services"
msgstr ""
......@@ -6928,6 +7099,45 @@ msgstr ""
msgid "Push to create a project"
msgstr ""
msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
msgstr ""
msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
msgstr ""
msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
msgstr ""
msgid "PushoverService|High Priority"
msgstr ""
msgid "PushoverService|Leave blank for all active devices"
msgstr ""
msgid "PushoverService|Low Priority"
msgstr ""
msgid "PushoverService|Lowest Priority"
msgstr ""
msgid "PushoverService|Normal Priority"
msgstr ""
msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
msgstr ""
msgid "PushoverService|See project %{project_full_name}"
msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
msgid "PushoverService|Your application key"
msgstr ""
msgid "PushoverService|Your user key"
msgstr ""
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
......@@ -7014,6 +7224,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
msgid "Remote object has no absolute path."
msgstr ""
msgid "Remove"
msgstr ""
......@@ -8427,6 +8640,9 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
......@@ -8454,12 +8670,18 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
msgid "The project is still being deleted. Please try again later."
msgstr ""
msgid "The project was successfully forked."
msgstr ""
msgid "The project was successfully imported."
msgstr ""
msgid "The remote mirror took to long to complete."
msgstr ""
msgid "The remote repository is being updated..."
msgstr ""
......@@ -8559,6 +8781,9 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
msgid "There was an error loading users activity calendar."
msgstr ""
......@@ -8655,6 +8880,9 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
msgid "This is a confidential issue."
msgstr ""
......@@ -9196,6 +9424,12 @@ msgstr ""
msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
msgid "Unknown encryption strategy: %{encrypted_strategy}!"
msgstr ""
msgid "Unknown format"
msgstr ""
msgid "Unlock"
msgstr ""
......@@ -9292,6 +9526,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
msgid "Upload file does not exist"
msgstr ""
msgid "Upload object map"
msgstr ""
......@@ -9457,6 +9694,9 @@ msgstr ""
msgid "Users were successfully added."
msgstr ""
msgid "Using required encryption strategy when encrypted field is missing!"
msgstr ""
msgid "Validate"
msgstr ""
......@@ -10038,6 +10278,9 @@ msgstr ""
msgid "Your Todos"
msgstr ""
msgid "Your U2F device did not send a valid JSON response."
msgstr ""
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
......@@ -10119,6 +10362,12 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
msgid "already being used for another group or project milestone."
msgstr ""
msgid "already shared with this group"
msgstr ""
msgid "among other things"
msgstr ""
......@@ -10131,6 +10380,15 @@ msgstr ""
msgid "branch name"
msgstr ""
msgid "cannot be changed if a personal project has container registry tags."
msgstr ""
msgid "cannot be enabled unless all domains have TLS certificates"
msgstr ""
msgid "cannot include leading slash or directory traversal."
msgstr ""
msgid "commented on %{link_to_project}"
msgstr ""
......@@ -10174,9 +10432,15 @@ msgstr[1] ""
msgid "done"
msgstr ""
msgid "element is not a hierarchy"
msgstr ""
msgid "enabled"
msgstr ""
msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr ""
msgid "error"
msgstr ""
......@@ -10210,6 +10474,9 @@ msgstr ""
msgid "group"
msgstr ""
msgid "has already been taken"
msgstr ""
msgid "here"
msgstr ""
......@@ -10237,6 +10504,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
msgid "is not an email you own"
msgstr ""
msgid "issue boards"
msgstr ""
......@@ -10269,6 +10539,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "milestone should belong either to a project or a group."
msgstr ""
msgid "missing"
msgstr ""
......@@ -10476,9 +10749,15 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
msgid "must be greater than start date"
msgstr ""
msgid "n/a"
msgstr ""
msgid "needs to be beetween 10 minutes and 1 month"
msgstr ""
msgid "new merge request"
msgstr ""
......@@ -10566,6 +10845,9 @@ msgstr ""
msgid "source diff"
msgstr ""
msgid "specified top is not part of the tree"
msgstr ""
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment