rubustrings 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/rubustrings +4 -0
- data/lib/rubustrings.rb +11 -0
- data/lib/rubustrings/action.rb +147 -0
- metadata +49 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bbbadb6f88015382d88dbce31f356de8db8f8730
|
4
|
+
data.tar.gz: 8b3bd9483ee694595ad3c047e66a2890d468d95c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6d8eeac3b005bfaf6d7133aed1c574fd97cb652bd51619b37a48663e330a53aeb92804cec8955fce07b48b3817788e0d8ee691c4a21532391df5d9eef2d154f9
|
7
|
+
data.tar.gz: d76e61a91ea79bba6924838422b7ebfcce9c1f120d072ddde0a1db048f9eb7298b18cab34bd959157b1a304aa6bb6cc1fa78d1ea2907bf795f0ce22c05f16cf3
|
data/bin/rubustrings
ADDED
data/lib/rubustrings.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
|
2
|
+
require 'colored'
|
3
|
+
|
4
|
+
module Rubustrings
|
5
|
+
class Action
|
6
|
+
|
7
|
+
def validate(filenames)
|
8
|
+
abort 'No strings file provided' unless filenames
|
9
|
+
filenames.each do |file_name|
|
10
|
+
log_output(:info, '', 0, "Processing file: \"#{file_name}\"\n")
|
11
|
+
result = validate_localizable_string_file file_name
|
12
|
+
|
13
|
+
if result
|
14
|
+
log_output(:result_success, file_name, 0, 'Strings file validated succesfully')
|
15
|
+
exit 0
|
16
|
+
else
|
17
|
+
log_output(:result_error, file_name, 0, 'Some errors detected')
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Possible levels are :error, :result_error, :warning, :result_success, :info
|
24
|
+
def log_output(level, file_name, line_number, message)
|
25
|
+
message = message.chomp
|
26
|
+
case level
|
27
|
+
when :error
|
28
|
+
puts "#{file_name}:#{line_number}: error: #{message}"
|
29
|
+
when :warning
|
30
|
+
puts "#{file_name}:#{line_number}: warning: #{message}"
|
31
|
+
when :result_success
|
32
|
+
puts "\nResult: ✓ #{message}".bold.green
|
33
|
+
when :result_error
|
34
|
+
puts "\nResult: ✘ #{message}".bold.red
|
35
|
+
when :info
|
36
|
+
puts message.to_s.blue
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_localizable_string_file(file_name)
|
41
|
+
file_data = open_and_read_file file_name
|
42
|
+
cleaned_strings = remove_comments_and_empty_lines file_data
|
43
|
+
|
44
|
+
return log_output(:error, file_name, 0, "no translations found in file: #{file_name}") if cleaned_strings.empty?
|
45
|
+
|
46
|
+
validation_result = true
|
47
|
+
cleaned_strings.each_line do |line|
|
48
|
+
validation_result &= validate_translation_line file_name, line
|
49
|
+
end
|
50
|
+
validation_result
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_line_numbers(file_data)
|
54
|
+
line_num = 0
|
55
|
+
result = ''
|
56
|
+
file_data.each_line do |line|
|
57
|
+
line_num += 1
|
58
|
+
result += "#{line_num} #{line}"
|
59
|
+
end
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
def open_and_read_file(file_name)
|
64
|
+
return nil unless File.exist?(file_name)
|
65
|
+
|
66
|
+
begin
|
67
|
+
File.open(file_name, 'rb:utf-16:utf-8').read
|
68
|
+
rescue
|
69
|
+
File.open(file_name, 'rb:utf-8:utf-8').read
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def remove_comments_and_empty_lines(file_data)
|
74
|
+
multiline_comments_regex = %r{/\*.*?\*/}m
|
75
|
+
empty_lines_regex = /^[1-9]\d* $\n/
|
76
|
+
|
77
|
+
file_data_with_lines = add_line_numbers file_data
|
78
|
+
file_data_with_lines.gsub(multiline_comments_regex, '').gsub(empty_lines_regex, '') if file_data
|
79
|
+
end
|
80
|
+
|
81
|
+
def validate_format(line)
|
82
|
+
localizable_strings_format_regex = /^\"((?:\\.|[^\\"])*?)\"\s=\s\"((?:\\.|[^\\"])*?)\";/
|
83
|
+
localizable_strings_format_regex.match line
|
84
|
+
end
|
85
|
+
|
86
|
+
def validate_special_characters(translation_key, translation_value)
|
87
|
+
variables_regex = /%[hlqLztj]?[@%dDuUxXoOfeEgGcCsSpaAF]/
|
88
|
+
key_variables = translation_key.scan(variables_regex)
|
89
|
+
value_variables = translation_value.scan(variables_regex)
|
90
|
+
|
91
|
+
key_variables.sort == value_variables.sort
|
92
|
+
end
|
93
|
+
|
94
|
+
def validate_special_beginning(translation_key, translation_value)
|
95
|
+
beginning_regex = /^(?:\s|\n|\r)/
|
96
|
+
|
97
|
+
return true unless translation_key =~ beginning_regex || translation_value =~ beginning_regex
|
98
|
+
translation_key.chars.first == translation_value.chars.first
|
99
|
+
end
|
100
|
+
|
101
|
+
def validate_special_ending(translation_key, translation_value)
|
102
|
+
ending_regex = /(?:\s|\n|\r)$/
|
103
|
+
|
104
|
+
return true unless translation_key =~ ending_regex || translation_value =~ ending_regex
|
105
|
+
translation_key.chars.last == translation_value.chars.last
|
106
|
+
end
|
107
|
+
|
108
|
+
def check_translation_length(translation_key, translation_value)
|
109
|
+
translation_value.length / translation_key.length < 3
|
110
|
+
end
|
111
|
+
|
112
|
+
def validate_translation_line(file_name, line)
|
113
|
+
line_number = 0
|
114
|
+
|
115
|
+
empty_regex = /^\d+\s*\n?$/
|
116
|
+
return true if empty_regex.match line
|
117
|
+
|
118
|
+
numbered_line_regex = /^(\d+) (.*)/
|
119
|
+
numbered_line_match = numbered_line_regex.match line
|
120
|
+
|
121
|
+
return log_output(:error, file_name, line_number, 'internal error') unless numbered_line_match
|
122
|
+
line_number = numbered_line_match[1]
|
123
|
+
line = numbered_line_match[2]
|
124
|
+
|
125
|
+
match = validate_format line
|
126
|
+
return log_output(:error, file_name, line_number, "invalid format: #{line}") unless match
|
127
|
+
|
128
|
+
match_key = match[1]
|
129
|
+
match_value = match[2]
|
130
|
+
|
131
|
+
log_output(:warning, file_name, line_number, "no translated string: #{line}") if match_value.empty?
|
132
|
+
|
133
|
+
log_output(:warning, file_name, line_number, "translation significantly large: #{line}") unless check_translation_length match_key, match_value
|
134
|
+
|
135
|
+
validation_special_characters = validate_special_characters match_key, match_value
|
136
|
+
log_output(:error, file_name, line_number, "number of variables mismatch: #{line}") unless validation_special_characters
|
137
|
+
|
138
|
+
validation_special_beginning = validate_special_beginning match_key, match_value
|
139
|
+
log_output(:error, file_name, line_number, "beginning mismatch: #{line}") unless validation_special_beginning
|
140
|
+
|
141
|
+
validation_special_ending = validate_special_ending match_key, match_value
|
142
|
+
log_output(:error, file_name, line_number, "ending mismatch: #{line}") unless validation_special_ending
|
143
|
+
|
144
|
+
validation_special_characters && validation_special_beginning && validation_special_ending
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubustrings
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Cordero
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-03 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Check the format and consistency of the Localizable.strings files of
|
14
|
+
iOS Apps with multi-language support
|
15
|
+
email: dcorderoramirez@gmail.com
|
16
|
+
executables:
|
17
|
+
- rubustrings
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/rubustrings
|
22
|
+
- lib/rubustrings.rb
|
23
|
+
- lib/rubustrings/action.rb
|
24
|
+
homepage: https://github.com/dcordero/Rubustrings
|
25
|
+
licenses:
|
26
|
+
- MIT
|
27
|
+
metadata: {}
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubyforge_project:
|
44
|
+
rubygems_version: 2.6.11
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: Check Localizable.strings files of iOS Apps
|
48
|
+
test_files: []
|
49
|
+
has_rdoc:
|