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
......
This diff is collapsed.
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