Commit 5361c968 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'bvl-port-of-po-validation' into 'master'

Port of PO validation

See merge request gitlab-org/gitlab-ee!6183
parents bdced90b 5d30da67
...@@ -38,14 +38,17 @@ export default { ...@@ -38,14 +38,17 @@ export default {
return this.modifiedFilesLength ? 'multi-file-modified' : ''; return this.modifiedFilesLength ? 'multi-file-modified' : '';
}, },
additionsTooltip() { additionsTooltip() {
return sprintf(n__('1 %{type} addition', '%d %{type} additions', this.addedFilesLength), { return sprintf(n__('1 %{type} addition', '%{count} %{type} additions', this.addedFilesLength), {
type: this.title.toLowerCase(), type: this.title.toLowerCase(),
count: this.addedFilesLength,
}); });
}, },
modifiedTooltip() { modifiedTooltip() {
return sprintf( return sprintf(
n__('1 %{type} modification', '%d %{type} modifications', this.modifiedFilesLength), n__('1 %{type} modification', '%{count} %{type} modifications', this.modifiedFilesLength), {
{ type: this.title.toLowerCase() }, type: this.title.toLowerCase(),
count: this.modifiedFilesLength,
},
); );
}, },
titleTooltip() { titleTooltip() {
......
...@@ -177,8 +177,8 @@ export default { ...@@ -177,8 +177,8 @@ export default {
}); });
} }
return sprintf( return sprintf(
n__('%{type} detected %d vulnerability', '%{type} detected %d vulnerabilities', issuesCount), n__('%{type} detected 1 vulnerability', '%{type} detected %{vulnerabilityCount} vulnerabilities', issuesCount),
{ type }, { type, vulnerabilityCount: issuesCount },
); );
}, },
translateText(type) { translateText(type) {
......
...@@ -268,11 +268,11 @@ export const textBuilder = ( ...@@ -268,11 +268,11 @@ export const textBuilder = (
if (newIssues > 0) { if (newIssues > 0) {
return sprintf( return sprintf(
n__( n__(
'%{type} detected %d vulnerability for the source branch only', '%{type} detected 1 vulnerability for the source branch only',
'%{type} detected %d vulnerabilities for the source branch only', '%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only',
newIssues, newIssues,
), ),
{ type }, { type, vulnerabilityCount: newIssues },
); );
} }
...@@ -287,11 +287,11 @@ export const textBuilder = ( ...@@ -287,11 +287,11 @@ export const textBuilder = (
if (newIssues > 0 && resolvedIssues === 0) { if (newIssues > 0 && resolvedIssues === 0) {
return sprintf( return sprintf(
n__( n__(
'%{type} detected %d new vulnerability', '%{type} detected 1 new vulnerability',
'%{type} detected %d new vulnerabilities', '%{type} detected %{vulnerabilityCount} new vulnerabilities',
newIssues, newIssues,
), ),
{ type }, { type, vulnerabilityCount: newIssues },
); );
} }
...@@ -299,24 +299,24 @@ export const textBuilder = ( ...@@ -299,24 +299,24 @@ export const textBuilder = (
if (newIssues > 0 && resolvedIssues > 0) { if (newIssues > 0 && resolvedIssues > 0) {
return `${sprintf( return `${sprintf(
n__( n__(
'%{type} detected %d new vulnerability', '%{type} detected 1 new vulnerability',
'%{type} detected %d new vulnerabilities', '%{type} detected %{vulnerabilityCount} new vulnerabilities',
newIssues, newIssues,
), ),
{ type }, { type, vulnerabilityCount: newIssues },
)} )}
${n__('and %d fixed vulnerability', 'and %d fixed vulnerabilities', resolvedIssues)}`; ${n__('and 1 fixed vulnerability', 'and %d fixed vulnerabilities', resolvedIssues)}`;
} }
// with only fixed issues // with only fixed issues
if (newIssues === 0 && resolvedIssues > 0) { if (newIssues === 0 && resolvedIssues > 0) {
return sprintf( return sprintf(
n__( n__(
'%{type} detected %d fixed vulnerability', '%{type} detected 1 fixed vulnerability',
'%{type} detected %d fixed vulnerabilities', '%{type} detected %{vulnerabilityCount} fixed vulnerabilities',
resolvedIssues, resolvedIssues,
), ),
{ type }, { type, vulnerabilityCount: resolvedIssues },
); );
} }
} }
......
...@@ -21,7 +21,8 @@ module Gitlab ...@@ -21,7 +21,8 @@ module Gitlab
'nl_NL' => 'Nederlands', 'nl_NL' => 'Nederlands',
'tr_TR' => 'Türkçe', 'tr_TR' => 'Türkçe',
'id_ID' => 'Bahasa Indonesia', 'id_ID' => 'Bahasa Indonesia',
'fil_PH' => 'Filipino' 'fil_PH' => 'Filipino',
'pl_PL' => 'Polski'
}.freeze }.freeze
def available_locales def available_locales
......
...@@ -3,16 +3,25 @@ module Gitlab ...@@ -3,16 +3,25 @@ module Gitlab
class MetadataEntry class MetadataEntry
attr_reader :entry_data attr_reader :entry_data
# Avoid testing too many plurals if `nplurals` was incorrectly set.
# Based on info on https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
# which mentions special cases for numbers ending in 2 digits
MAX_FORMS_TO_TEST = 101
def initialize(entry_data) def initialize(entry_data)
@entry_data = entry_data @entry_data = entry_data
end end
def expected_plurals def expected_forms
return nil unless plural_information return nil unless plural_information
plural_information['nplurals'].to_i plural_information['nplurals'].to_i
end end
def forms_to_test
@forms_to_test ||= [expected_forms, MAX_FORMS_TO_TEST].compact.min
end
private private
def plural_information def plural_information
......
module Gitlab module Gitlab
module I18n module I18n
class PoLinter class PoLinter
include Gitlab::Utils::StrongMemoize
attr_reader :po_path, :translation_entries, :metadata_entry, :locale attr_reader :po_path, :translation_entries, :metadata_entry, :locale
VARIABLE_REGEX = /%{\w*}|%[a-z]/.freeze VARIABLE_REGEX = /%{\w*}|%[a-z]/.freeze
...@@ -34,7 +36,7 @@ module Gitlab ...@@ -34,7 +36,7 @@ module Gitlab
end end
@translation_entries = entries.map do |entry_data| @translation_entries = entries.map do |entry_data|
Gitlab::I18n::TranslationEntry.new(entry_data, metadata_entry.expected_plurals) Gitlab::I18n::TranslationEntry.new(entry_data, metadata_entry.expected_forms)
end end
nil nil
...@@ -48,7 +50,7 @@ module Gitlab ...@@ -48,7 +50,7 @@ module Gitlab
translation_entries.each do |entry| translation_entries.each do |entry|
errors_for_entry = validate_entry(entry) errors_for_entry = validate_entry(entry)
errors[join_message(entry.msgid)] = errors_for_entry if errors_for_entry.any? errors[entry.msgid] = errors_for_entry if errors_for_entry.any?
end end
errors errors
...@@ -62,6 +64,7 @@ module Gitlab ...@@ -62,6 +64,7 @@ module Gitlab
validate_newlines(errors, entry) validate_newlines(errors, entry)
validate_number_of_plurals(errors, entry) validate_number_of_plurals(errors, entry)
validate_unescaped_chars(errors, entry) validate_unescaped_chars(errors, entry)
validate_translation(errors, entry)
errors errors
end end
...@@ -81,35 +84,39 @@ module Gitlab ...@@ -81,35 +84,39 @@ module Gitlab
end end
def validate_number_of_plurals(errors, entry) def validate_number_of_plurals(errors, entry)
return unless metadata_entry&.expected_plurals return unless metadata_entry&.expected_forms
return unless entry.translated? return unless entry.translated?
if entry.has_plural? && entry.all_translations.size != metadata_entry.expected_plurals if entry.has_plural? && entry.all_translations.size != metadata_entry.expected_forms
errors << "should have #{metadata_entry.expected_plurals} "\ errors << "should have #{metadata_entry.expected_forms} "\
"#{'translations'.pluralize(metadata_entry.expected_plurals)}" "#{'translations'.pluralize(metadata_entry.expected_forms)}"
end end
end end
def validate_newlines(errors, entry) def validate_newlines(errors, entry)
if entry.msgid_contains_newlines? if entry.msgid_has_multiple_lines?
errors << 'is defined over multiple lines, this breaks some tooling.' errors << 'is defined over multiple lines, this breaks some tooling.'
end end
if entry.plural_id_contains_newlines? if entry.plural_id_has_multiple_lines?
errors << 'plural is defined over multiple lines, this breaks some tooling.' errors << 'plural is defined over multiple lines, this breaks some tooling.'
end end
if entry.translations_contain_newlines? if entry.translations_have_multiple_lines?
errors << 'has translations defined over multiple lines, this breaks some tooling.' errors << 'has translations defined over multiple lines, this breaks some tooling.'
end end
end end
def validate_variables(errors, entry) def validate_variables(errors, entry)
if entry.has_singular_translation? if entry.has_singular_translation?
validate_variables_in_message(errors, entry.msgid, entry.msgid)
validate_variables_in_message(errors, entry.msgid, entry.singular_translation) validate_variables_in_message(errors, entry.msgid, entry.singular_translation)
end end
if entry.has_plural? if entry.has_plural?
validate_variables_in_message(errors, entry.plural_id, entry.plural_id)
entry.plural_translations.each do |translation| entry.plural_translations.each do |translation|
validate_variables_in_message(errors, entry.plural_id, translation) validate_variables_in_message(errors, entry.plural_id, translation)
end end
...@@ -117,26 +124,19 @@ module Gitlab ...@@ -117,26 +124,19 @@ module Gitlab
end end
def validate_variables_in_message(errors, message_id, message_translation) def validate_variables_in_message(errors, message_id, message_translation)
message_id = join_message(message_id)
required_variables = message_id.scan(VARIABLE_REGEX) required_variables = message_id.scan(VARIABLE_REGEX)
validate_unnamed_variables(errors, required_variables) validate_unnamed_variables(errors, required_variables)
validate_translation(errors, message_id, required_variables)
validate_variable_usage(errors, message_translation, required_variables) validate_variable_usage(errors, message_translation, required_variables)
end end
def validate_translation(errors, message_id, used_variables) def validate_translation(errors, entry)
variables = fill_in_variables(used_variables)
begin
Gitlab::I18n.with_locale(locale) do Gitlab::I18n.with_locale(locale) do
translated = if message_id.include?('|') if entry.has_plural?
FastGettext::Translation.s_(message_id) translate_plural(entry)
else else
FastGettext::Translation._(message_id) translate_singular(entry)
end end
translated % variables
end end
# `sprintf` could raise an `ArgumentError` when invalid passing something # `sprintf` could raise an `ArgumentError` when invalid passing something
...@@ -151,7 +151,71 @@ module Gitlab ...@@ -151,7 +151,71 @@ module Gitlab
# `FastGettext::Translation` could raise `ArgumentError` as subclassess # `FastGettext::Translation` could raise `ArgumentError` as subclassess
# `InvalidEncoding`, `IllegalSequence` & `InvalidCharacter` # `InvalidEncoding`, `IllegalSequence` & `InvalidCharacter`
rescue ArgumentError, TypeError, RuntimeError => e rescue ArgumentError, TypeError, RuntimeError => e
errors << "Failure translating to #{locale} with #{variables}: #{e.message}" errors << "Failure translating to #{locale}: #{e.message}"
end
def translate_singular(entry)
used_variables = entry.msgid.scan(VARIABLE_REGEX)
variables = fill_in_variables(used_variables)
translation = if entry.msgid.include?('|')
FastGettext::Translation.s_(entry.msgid)
else
FastGettext::Translation._(entry.msgid)
end
translation % variables if used_variables.any?
end
def translate_plural(entry)
used_variables = entry.plural_id.scan(VARIABLE_REGEX)
variables = fill_in_variables(used_variables)
numbers_covering_all_plurals.map do |number|
translation = FastGettext::Translation.n_(entry.msgid, entry.plural_id, number)
translation % variables if used_variables.any?
end
end
def numbers_covering_all_plurals
@numbers_covering_all_plurals ||= calculate_numbers_covering_all_plurals
end
def calculate_numbers_covering_all_plurals
required_numbers = []
discovered_indexes = []
counter = 0
while discovered_indexes.size < metadata_entry.forms_to_test && counter < Gitlab::I18n::MetadataEntry::MAX_FORMS_TO_TEST
index_for_count = index_for_pluralization(counter)
unless discovered_indexes.include?(index_for_count)
discovered_indexes << index_for_count
required_numbers << counter
end
counter += 1
end
required_numbers
end
def index_for_pluralization(counter)
# This calls the C function that defines the pluralization rule, it can
# return a boolean (`false` represents 0, `true` represents 1) or an integer
# that specifies the plural form to be used for the given number
pluralization_result = Gitlab::I18n.with_locale(locale) do
FastGettext.pluralisation_rule.call(counter)
end
case pluralization_result
when false
0
when true
1
else
pluralization_result
end end
end end
...@@ -172,14 +236,18 @@ module Gitlab ...@@ -172,14 +236,18 @@ module Gitlab
end end
def validate_unnamed_variables(errors, variables) def validate_unnamed_variables(errors, variables)
if variables.size > 1 && variables.any? { |variable_name| unnamed_variable?(variable_name) } unnamed_variables, named_variables = variables.partition { |name| unnamed_variable?(name) }
if unnamed_variables.any? && named_variables.any?
errors << 'is combining named variables with unnamed variables'
end
if unnamed_variables.size > 1
errors << 'is combining multiple unnamed variables' errors << 'is combining multiple unnamed variables'
end end
end end
def validate_variable_usage(errors, translation, required_variables) def validate_variable_usage(errors, translation, required_variables)
translation = join_message(translation)
# We don't need to validate when the message is empty. # We don't need to validate when the message is empty.
# In this case we fall back to the default, which has all the the # In this case we fall back to the default, which has all the the
# required variables. # required variables.
...@@ -205,10 +273,6 @@ module Gitlab ...@@ -205,10 +273,6 @@ module Gitlab
def validate_flags(errors, entry) def validate_flags(errors, entry)
errors << "is marked #{entry.flag}" if entry.flag errors << "is marked #{entry.flag}" if entry.flag
end end
def join_message(message)
Array(message).join
end
end end
end end
end end
...@@ -11,11 +11,11 @@ module Gitlab ...@@ -11,11 +11,11 @@ module Gitlab
end end
def msgid def msgid
entry_data[:msgid] @msgid ||= Array(entry_data[:msgid]).join
end end
def plural_id def plural_id
entry_data[:msgid_plural] @plural_id ||= Array(entry_data[:msgid_plural]).join
end end
def has_plural? def has_plural?
...@@ -23,12 +23,11 @@ module Gitlab ...@@ -23,12 +23,11 @@ module Gitlab
end end
def singular_translation def singular_translation
all_translations.first if has_singular_translation? all_translations.first.to_s if has_singular_translation?
end end
def all_translations def all_translations
@all_translations ||= entry_data.fetch_values(*translation_keys) @all_translations ||= translation_entries.map { |translation| Array(translation).join }
.reject(&:empty?)
end end
def translated? def translated?
...@@ -54,16 +53,16 @@ module Gitlab ...@@ -54,16 +53,16 @@ module Gitlab
nplurals > 1 || !has_plural? nplurals > 1 || !has_plural?
end end
def msgid_contains_newlines? def msgid_has_multiple_lines?
msgid.is_a?(Array) entry_data[:msgid].is_a?(Array)
end end
def plural_id_contains_newlines? def plural_id_has_multiple_lines?
plural_id.is_a?(Array) entry_data[:msgid_plural].is_a?(Array)
end end
def translations_contain_newlines? def translations_have_multiple_lines?
all_translations.any? { |translation| translation.is_a?(Array) } translation_entries.any? { |translation| translation.is_a?(Array) }
end end
def msgid_contains_unescaped_chars? def msgid_contains_unescaped_chars?
...@@ -84,6 +83,11 @@ module Gitlab ...@@ -84,6 +83,11 @@ module Gitlab
private private
def translation_entries
@translation_entries ||= entry_data.fetch_values(*translation_keys)
.reject(&:empty?)
end
def translation_keys def translation_keys
@translation_keys ||= entry_data.keys.select { |key| key.to_s =~ /\Amsgstr(\[\d+\])?\z/ } @translation_keys ||= entry_data.keys.select { |key| key.to_s =~ /\Amsgstr(\[\d+\])?\z/ }
end end
......
...@@ -50,6 +50,32 @@ namespace :gettext do ...@@ -50,6 +50,32 @@ namespace :gettext do
end end
end end
task :updated_check do
# Removing all pre-translated files speeds up `gettext:find` as the
# files don't need to be merged.
`rm locale/*/gitlab.po`
# `gettext:find` writes touches to temp files to `stderr` which would cause
# `static-analysis` to report failures. We can ignore these
silence_stream(STDERR) { Rake::Task['gettext:find'].invoke }
changed_files = `git diff --name-only`.lines.map(&:strip)
# reset the locale folder for potential next tasks
`git checkout -- locale`
if changed_files.include?('locale/gitlab.pot')
raise <<~MSG
Newly translated strings found, please add them to `gitlab.pot` by running:
bundle exec rake gettext:find; git checkout -- locale/*/gitlab.po;
Then commit and push the resulting changes to `locale/gitlab.pot`.
MSG
end
end
def report_errors_for_file(file, errors_for_file) def report_errors_for_file(file, errors_for_file)
puts "Errors in `#{file}`:" puts "Errors in `#{file}`:"
......
...@@ -27,6 +27,7 @@ unless Rails.env.production? ...@@ -27,6 +27,7 @@ unless Rails.env.production?
scss_lint scss_lint
flay flay
gettext:lint gettext:lint
gettext:updated_check
lint:static_verification lint:static_verification
].each do |task| ].each do |task|
pid = Process.fork do pid = Process.fork do
......
...@@ -8,8 +8,8 @@ msgid "" ...@@ -8,8 +8,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gitlab 1.0.0\n" "Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-06-13 10:31-0400\n" "POT-Creation-Date: 2018-06-19 13:14+0200\n"
"PO-Revision-Date: 2018-06-13 10:31-0400\n" "PO-Revision-Date: 2018-06-19 13:14+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n" "Language: \n"
...@@ -140,8 +140,8 @@ msgstr "" ...@@ -140,8 +140,8 @@ msgstr ""
msgid "%{title} changes" msgid "%{title} changes"
msgstr "" msgstr ""
msgid "%{type} detected %d vulnerability" msgid "%{type} detected 1 vulnerability"
msgid_plural "%{type} detected %d vulnerabilities" msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
...@@ -164,12 +164,12 @@ msgid "- show less" ...@@ -164,12 +164,12 @@ msgid "- show less"
msgstr "" msgstr ""
msgid "1 %{type} addition" msgid "1 %{type} addition"
msgid_plural "%d %{type} additions" msgid_plural "%{count} %{type} additions"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "1 %{type} modification" msgid "1 %{type} modification"
msgid_plural "%d %{type} modifications" msgid_plural "%{count} %{type} modifications"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
...@@ -1411,6 +1411,12 @@ msgstr "" ...@@ -1411,6 +1411,12 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project" msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "" msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
msgid "ClusterIntegration|Learn more about %{link_to_documentation}" msgid "ClusterIntegration|Learn more about %{link_to_documentation}"
msgstr "" msgstr ""
...@@ -1507,9 +1513,6 @@ msgstr "" ...@@ -1507,9 +1513,6 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster" msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "" msgstr ""
msgid "ClusterIntegration|See zones"
msgstr ""
msgid "ClusterIntegration|Select machine type" msgid "ClusterIntegration|Select machine type"
msgstr "" msgstr ""
...@@ -1826,6 +1829,9 @@ msgstr "" ...@@ -1826,6 +1829,9 @@ msgstr ""
msgid "Control the maximum concurrency of repository backfill for this secondary node" msgid "Control the maximum concurrency of repository backfill for this secondary node"
msgstr "" msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
msgid "Copy SSH public key to clipboard" msgid "Copy SSH public key to clipboard"
msgstr "" msgstr ""
...@@ -2368,9 +2374,6 @@ msgstr "" ...@@ -2368,9 +2374,6 @@ msgstr ""
msgid "Error Reporting and Logging" msgid "Error Reporting and Logging"
msgstr "" msgstr ""
msgid "Error checking branch data. Please try again."
msgstr ""
msgid "Error committing changes. Please try again." msgid "Error committing changes. Please try again."
msgstr "" msgstr ""
...@@ -2778,6 +2781,9 @@ msgstr "" ...@@ -2778,6 +2781,9 @@ msgstr ""
msgid "Geo|Shards to synchronize" msgid "Geo|Shards to synchronize"
msgstr "" msgstr ""
msgid "Geo|Verification capacity"
msgstr ""
msgid "Git repository URL" msgid "Git repository URL"
msgstr "" msgstr ""
...@@ -3032,6 +3038,15 @@ msgstr "" ...@@ -3032,6 +3038,15 @@ msgstr ""
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>." msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
msgstr "" msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr ""
msgid "ImageDiffViewer|Onion skin"
msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
msgid "Import" msgid "Import"
msgstr "" msgstr ""
...@@ -3501,6 +3516,9 @@ msgstr "" ...@@ -3501,6 +3516,9 @@ msgstr ""
msgid "Months" msgid "Months"
msgstr "" msgstr ""
msgid "More actions"
msgstr ""
msgid "More info" msgid "More info"
msgstr "" msgstr ""
...@@ -4947,7 +4965,7 @@ msgstr "" ...@@ -4947,7 +4965,7 @@ msgstr ""
msgid "Stage" msgid "Stage"
msgstr "" msgstr ""
msgid "Stage all" msgid "Stage all changes"
msgstr "" msgstr ""
msgid "Stage changes" msgid "Stage changes"
...@@ -5628,7 +5646,7 @@ msgstr "" ...@@ -5628,7 +5646,7 @@ msgstr ""
msgid "Unresolve discussion" msgid "Unresolve discussion"
msgstr "" msgstr ""
msgid "Unstage all" msgid "Unstage all changes"
msgstr "" msgstr ""
msgid "Unstage changes" msgid "Unstage changes"
...@@ -5979,7 +5997,7 @@ msgstr "" ...@@ -5979,7 +5997,7 @@ msgstr ""
msgid "You are on a read-only GitLab instance." msgid "You are on a read-only GitLab instance."
msgstr "" msgstr ""
msgid "You are on a secondary (read-only) Geo node. If you want to make any changes, you must visit the %{primary_node}." msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
msgstr "" msgstr ""
msgid "You can also create a project from the command line." msgid "You can also create a project from the command line."
...@@ -6111,7 +6129,7 @@ msgstr "" ...@@ -6111,7 +6129,7 @@ msgstr ""
msgid "among other things" msgid "among other things"
msgstr "" msgstr ""
msgid "and %d fixed vulnerability" msgid "and 1 fixed vulnerability"
msgid_plural "and %d fixed vulnerabilities" msgid_plural "and %d fixed vulnerabilities"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
......
...@@ -232,6 +232,9 @@ describe('security reports utils', () => { ...@@ -232,6 +232,9 @@ describe('security reports utils', () => {
expect(textBuilder('', { head: 'foo', base: 'foo' }, 1, 0, 0)).toEqual( expect(textBuilder('', { head: 'foo', base: 'foo' }, 1, 0, 0)).toEqual(
' detected 1 new vulnerability', ' detected 1 new vulnerability',
); );
expect(textBuilder('', { head: 'foo', base: 'foo' }, 2, 0, 0)).toEqual(
' detected 2 new vulnerabilities',
);
}); });
}); });
...@@ -240,6 +243,9 @@ describe('security reports utils', () => { ...@@ -240,6 +243,9 @@ describe('security reports utils', () => {
expect( expect(
textBuilder('', { head: 'foo', base: 'foo' }, 1, 1, 0).replace(/\n+\s+/m, ' '), textBuilder('', { head: 'foo', base: 'foo' }, 1, 1, 0).replace(/\n+\s+/m, ' '),
).toEqual(' detected 1 new vulnerability and 1 fixed vulnerability'); ).toEqual(' detected 1 new vulnerability and 1 fixed vulnerability');
expect(
textBuilder('', { head: 'foo', base: 'foo' }, 2, 2, 0).replace(/\n+\s+/m, ' '),
).toEqual(' detected 2 new vulnerabilities and 2 fixed vulnerabilities');
}); });
}); });
...@@ -248,6 +254,9 @@ describe('security reports utils', () => { ...@@ -248,6 +254,9 @@ describe('security reports utils', () => {
expect(textBuilder('', { head: 'foo', base: 'foo' }, 0, 1, 0)).toEqual( expect(textBuilder('', { head: 'foo', base: 'foo' }, 0, 1, 0)).toEqual(
' detected 1 fixed vulnerability', ' detected 1 fixed vulnerability',
); );
expect(textBuilder('', { head: 'foo', base: 'foo' }, 0, 2, 0)).toEqual(
' detected 2 fixed vulnerabilities',
);
}); });
}); });
}); });
......
require 'spec_helper' require 'spec_helper'
describe Gitlab::I18n::MetadataEntry do describe Gitlab::I18n::MetadataEntry do
describe '#expected_plurals' do describe '#expected_forms' do
it 'returns the number of plurals' do it 'returns the number of plurals' do
data = { data = {
msgid: "", msgid: "",
...@@ -22,7 +22,7 @@ describe Gitlab::I18n::MetadataEntry do ...@@ -22,7 +22,7 @@ describe Gitlab::I18n::MetadataEntry do
} }
entry = described_class.new(data) entry = described_class.new(data)
expect(entry.expected_plurals).to eq(2) expect(entry.expected_forms).to eq(2)
end end
it 'returns 0 for the POT-metadata' do it 'returns 0 for the POT-metadata' do
...@@ -45,7 +45,7 @@ describe Gitlab::I18n::MetadataEntry do ...@@ -45,7 +45,7 @@ describe Gitlab::I18n::MetadataEntry do
} }
entry = described_class.new(data) entry = described_class.new(data)
expect(entry.expected_plurals).to eq(0) expect(entry.expected_forms).to eq(0)
end end
end end
end end
This diff is collapsed.
...@@ -109,7 +109,7 @@ describe Gitlab::I18n::TranslationEntry do ...@@ -109,7 +109,7 @@ describe Gitlab::I18n::TranslationEntry do
data = { msgid: %w(hello world) } data = { msgid: %w(hello world) }
entry = described_class.new(data, 2) entry = described_class.new(data, 2)
expect(entry.msgid_contains_newlines?).to be_truthy expect(entry.msgid_has_multiple_lines?).to be_truthy
end end
end end
...@@ -118,7 +118,7 @@ describe Gitlab::I18n::TranslationEntry do ...@@ -118,7 +118,7 @@ describe Gitlab::I18n::TranslationEntry do
data = { msgid_plural: %w(hello world) } data = { msgid_plural: %w(hello world) }
entry = described_class.new(data, 2) entry = described_class.new(data, 2)
expect(entry.plural_id_contains_newlines?).to be_truthy expect(entry.plural_id_has_multiple_lines?).to be_truthy
end end
end end
...@@ -127,7 +127,7 @@ describe Gitlab::I18n::TranslationEntry do ...@@ -127,7 +127,7 @@ describe Gitlab::I18n::TranslationEntry do
data = { msgstr: %w(hello world) } data = { msgstr: %w(hello world) }
entry = described_class.new(data, 2) entry = described_class.new(data, 2)
expect(entry.translations_contain_newlines?).to be_truthy expect(entry.translations_have_multiple_lines?).to be_truthy
end end
end end
......
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