forked from Katello/katello
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheck-gettext.rb
executable file
·142 lines (124 loc) · 4.45 KB
/
check-gettext.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/ruby
require 'optparse'
default_options = {:dir => File.expand_path("../..", __FILE__)}
options = default_options.dup
parser = OptionParser.new do |opts|
opts.banner = <<DESC
Find (and possibly fix) malformed gettext strings such as:
_("This is a malformed string with \#{interpolated_variable} within")
# should be _("This is a malformed string with %s within") % interpolated_variable
_("This is a malformed string with %s, and another %s") % [var1, var2]
# should be _("This is a malformed string with %{var1}, and another %{var2}") %
# {:var1 => var1, :var2 => var2}
It exits with 0 unless some problems found
DESC
opts.on("-d", "--dir DIR", "Directory with the source code") do |val|
options[:dir] = val
end
opts.on("-i", "--interpolations", "Find malformed interpolations") do
options[:interpolations] = true
end
opts.on("-m", "--multivars", "Find strings with more anonymous variables") do
options[:multivars] = true
end
opts.on("-f", "--fix", "Try to fix the malformed strings in the source") do
options[:fix] = true
end
end
parser.parse!
malformed_strings = Hash.new { |h, k| h[k] = [] }
dir = options[:dir]
dir << '/' unless dir.end_with?('/')
Dir.glob(File.join(dir, "**", "*")).each do |file|
next if File.directory?(file)
next if File.symlink?(file)
next if file.include?("/vendor/converge-ui/") # we skip converge-ui for now
next if file.end_with?("check-gettext.rb") # we don't check this very file
relative_file = file.sub(/^#{Regexp.escape(dir)}/, "")
file_content = File.read(file)
begin
gettext_strings = file_content.scan(/(_\(".*?"\))(.*)$/).map do |(string, suffix)|
if suffix.to_s.include?(".replace") # this is javascript and it uses different tool
next
end
if suffix = suffix.to_s[/(\s*%\s*.*$)/]
parts = suffix.split(/(\])/)
suffix = parts.reduce("") do |str, part|
str << part
break str if str.count("[") == str.count("]")
str
end
end
[string, suffix]
end
gettext_strings.compact
rescue ArgumentError
next # we can't scan binary files, skipping
end
if options[:interpolations]
found_strings = gettext_strings.find_all do |(s, suffix)|
s =~ /#\{.*?\}/
end
malformed_strings[relative_file].concat(found_strings.map(&:first))
found_strings.each do |(malformed, malformed_suffix)|
puts "#{relative_file}: #{malformed}"
if options[:fix]
variables = malformed.scan(/#\{(.*?)\}/).map(&:first)
fixed = malformed.gsub(/#\{.*?\}/, "%s")
fixed << " % "
if variables.size == 1
fixed << variables.first
else
fixed << "["
fixed << variables.join(", ")
fixed << "]"
end
file_content.gsub!(malformed, fixed)
end
end
end
if options[:multivars]
found_strings = gettext_strings.find_all do |(s, suffix)|
s.scan(/%[a-z]/).size > 1
end
malformed_strings[relative_file].concat(found_strings)
found_strings.each do |(malformed, malformed_suffix)|
puts "#{relative_file}: #{malformed}#{malformed_suffix}"
if options[:fix]
if malformed_suffix =~ /\s*%\s*\[(.*)\]/
# rubocop:disable AvoidPerlBackrefs
array_vars = $1.split(",").map(&:strip)
puts "Are this the variables used in the string?:"
puts array_vars.inspect
puts "[y/n]"
if gets.chomp == "y"
mapping = array_vars.reduce({}) do |h, var|
puts "Write alias for #{var}"
h.update(var => gets.chomp)
end
fixed, fixed_suffix = malformed.dup, []
array_vars.each do |var|
fixed.sub!(/%\w+/, "%{#{mapping[var]}}")
fixed_suffix << ":#{mapping[var]} => #{var}"
end
fixed_suffix = " % {#{fixed_suffix.join(", ")}}"
puts "Fixing to: #{fixed}#{fixed_suffix}"
file_content.gsub!("#{malformed}#{malformed_suffix}", "#{fixed}#{fixed_suffix}")
else
puts "In that case you have to fix it manually"
end
else
puts "This script is too dummy to solve this, please fix this manually"
end
end
end
end
File.write(file, file_content) if options[:fix]
end
malformed_strings_count = malformed_strings.values.flatten(1).size
if malformed_strings_count == 0
exit 0
else
STDERR.puts("Found #{malformed_strings_count} malformed strings")
exit 1
end