twine 0.8.0 → 0.8.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 +4 -4
- data/lib/twine.rb +1 -1
- data/lib/twine/cli.rb +7 -1
- data/lib/twine/formatters.rb +7 -13
- data/lib/twine/formatters/abstract.rb +38 -33
- data/lib/twine/formatters/android.rb +12 -5
- data/lib/twine/formatters/apple.rb +11 -5
- data/lib/twine/formatters/django.rb +18 -10
- data/lib/twine/formatters/flash.rb +11 -5
- data/lib/twine/formatters/gettext.rb +26 -19
- data/lib/twine/formatters/jquery.rb +11 -14
- data/lib/twine/formatters/tizen.rb +11 -30
- data/lib/twine/runner.rb +66 -56
- data/lib/twine/version.rb +1 -1
- data/test/command_test_case.rb +4 -2
- data/test/fixtures/formatter_django.po +1 -1
- data/test/fixtures/formatter_flash.properties +1 -1
- data/test/test_abstract_formatter.rb +21 -8
- data/test/test_cli.rb +22 -2
- data/test/test_formatters.rb +17 -8
- data/test/test_generate_all_string_files.rb +34 -2
- data/test/test_generate_loc_drop.rb +30 -0
- data/test/test_generate_string_file.rb +34 -3
- data/test/test_validate_strings_file.rb +11 -5
- data/test/twine_test_case.rb +5 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebc7f372d107cb4c3b9a12da92b792c510209d59
|
4
|
+
data.tar.gz: 72ccda8290612adfc0f7ac75f86756bc1d945333
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44bf1d87f0b3e88e70cc8962dd708a35866a74710e95706ae5e4061c02995b00afb6175acb1d5219605ec391b60ceeddf01edb83bd253d73e14681847cd8aac6
|
7
|
+
data.tar.gz: ea504d997033b778bb9f458fb33ef1f75bfb4d57c6da1771685f092c3fa1b2362f8bdf82d2a85cbcaade440c42617f21e130c7baab7767f5522f27843f78ca5f
|
data/lib/twine.rb
CHANGED
@@ -23,11 +23,11 @@ module Twine
|
|
23
23
|
|
24
24
|
require 'twine/plugin'
|
25
25
|
require 'twine/cli'
|
26
|
+
require 'twine/stringsfile'
|
26
27
|
require 'twine/encoding'
|
27
28
|
require 'twine/output_processor'
|
28
29
|
require 'twine/placeholders'
|
29
30
|
require 'twine/formatters'
|
30
31
|
require 'twine/runner'
|
31
|
-
require 'twine/stringsfile'
|
32
32
|
require 'twine/version'
|
33
33
|
end
|
data/lib/twine/cli.rb
CHANGED
@@ -46,7 +46,7 @@ module Twine
|
|
46
46
|
opts.on('-u', '--untagged', 'If you have specified tags using the --tags flag, then only those tags will be selected. If you also want to select all strings that are untagged, then you can specify this option to do so.') do |u|
|
47
47
|
options[:untagged] = true
|
48
48
|
end
|
49
|
-
formats = Formatters.formatters.map
|
49
|
+
formats = Formatters.formatters.map(&:format_name)
|
50
50
|
opts.on('-f', '--format FORMAT', "The file format to read or write (#{formats.join(', ')}). Additional formatters can be placed in the formats/ directory.") do |format|
|
51
51
|
unless formats.include?(format.downcase)
|
52
52
|
raise Twine::Error.new "Invalid format: #{format}"
|
@@ -89,6 +89,12 @@ module Twine
|
|
89
89
|
end
|
90
90
|
options[:output_encoding] = e
|
91
91
|
end
|
92
|
+
opts.on('--validate', 'Validate the strings file before formatting it') do
|
93
|
+
options[:validate] = true
|
94
|
+
end
|
95
|
+
opts.on('-p', '--pedantic', 'When validating a strings file, perform additional checks that go beyond pure validity (like presence of tags)') do
|
96
|
+
options[:pedantic] = true
|
97
|
+
end
|
92
98
|
opts.on('-h', '--help', 'Show this message.') do |h|
|
93
99
|
puts opts.help
|
94
100
|
exit
|
data/lib/twine/formatters.rb
CHANGED
@@ -1,15 +1,6 @@
|
|
1
|
-
require 'twine/formatters/abstract'
|
2
|
-
require 'twine/formatters/android'
|
3
|
-
require 'twine/formatters/apple'
|
4
|
-
require 'twine/formatters/flash'
|
5
|
-
require 'twine/formatters/gettext'
|
6
|
-
require 'twine/formatters/jquery'
|
7
|
-
require 'twine/formatters/django'
|
8
|
-
require 'twine/formatters/tizen'
|
9
|
-
|
10
1
|
module Twine
|
11
2
|
module Formatters
|
12
|
-
@formatters = [
|
3
|
+
@formatters = []
|
13
4
|
|
14
5
|
class << self
|
15
6
|
attr_reader :formatters
|
@@ -22,9 +13,12 @@ module Twine
|
|
22
13
|
# returns array of active formatters
|
23
14
|
#
|
24
15
|
def register_formatter formatter_class
|
25
|
-
|
26
|
-
@formatters << formatter_class
|
16
|
+
@formatters << formatter_class.new
|
27
17
|
end
|
28
18
|
end
|
29
19
|
end
|
30
|
-
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir[File.join(File.dirname(__FILE__), 'formatters', '*.rb')].each do |file|
|
23
|
+
require file
|
24
|
+
end
|
@@ -3,17 +3,28 @@ require 'fileutils'
|
|
3
3
|
module Twine
|
4
4
|
module Formatters
|
5
5
|
class Abstract
|
6
|
-
|
7
|
-
|
6
|
+
attr_accessor :strings
|
7
|
+
attr_accessor :options
|
8
8
|
|
9
|
-
def
|
10
|
-
|
9
|
+
def initialize
|
10
|
+
@strings = StringsFile.new
|
11
|
+
@options = {}
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
def format_name
|
15
|
+
raise NotImplementedError.new("You must implement format_name in your formatter class.")
|
16
|
+
end
|
17
|
+
|
18
|
+
def extension
|
19
|
+
raise NotImplementedError.new("You must implement extension in your formatter class.")
|
20
|
+
end
|
21
|
+
|
22
|
+
def can_handle_directory?(path)
|
23
|
+
raise NotImplementedError.new("You must implement can_handle_directory? in your formatter class.")
|
24
|
+
end
|
25
|
+
|
26
|
+
def default_file_name
|
27
|
+
raise NotImplementedError.new("You must implement default_file_name in your formatter class.")
|
17
28
|
end
|
18
29
|
|
19
30
|
def set_translation_for_key(key, lang, value)
|
@@ -64,10 +75,6 @@ module Twine
|
|
64
75
|
end
|
65
76
|
end
|
66
77
|
|
67
|
-
def default_file_name
|
68
|
-
raise NotImplementedError.new("You must implement default_file_name in your formatter class.")
|
69
|
-
end
|
70
|
-
|
71
78
|
def determine_language_given_path(path)
|
72
79
|
raise NotImplementedError.new("You must implement determine_language_given_path in your formatter class.")
|
73
80
|
end
|
@@ -92,21 +99,25 @@ module Twine
|
|
92
99
|
|
93
100
|
def format_sections(strings, lang)
|
94
101
|
sections = strings.sections.map { |section| format_section(section, lang) }
|
95
|
-
sections.join("\n")
|
102
|
+
sections.compact.join("\n")
|
96
103
|
end
|
97
104
|
|
98
105
|
def format_section_header(section)
|
99
106
|
end
|
100
107
|
|
108
|
+
def should_include_row(row, lang)
|
109
|
+
row.translated_string_for_lang(lang)
|
110
|
+
end
|
111
|
+
|
101
112
|
def format_section(section, lang)
|
102
|
-
rows = section.rows.
|
113
|
+
rows = section.rows.select { |row| should_include_row(row, lang) }
|
114
|
+
return if rows.empty?
|
103
115
|
|
104
116
|
result = ""
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
117
|
+
|
118
|
+
if section.name && section.name.length > 0
|
119
|
+
section_header = format_section_header(section)
|
120
|
+
result += "\n#{section_header}" if section_header
|
110
121
|
end
|
111
122
|
|
112
123
|
rows.map! { |row| format_row(row, lang) }
|
@@ -115,16 +126,8 @@ module Twine
|
|
115
126
|
result += rows.join
|
116
127
|
end
|
117
128
|
|
118
|
-
def row_pattern
|
119
|
-
"%{comment}%{key_value}"
|
120
|
-
end
|
121
|
-
|
122
129
|
def format_row(row, lang)
|
123
|
-
|
124
|
-
|
125
|
-
result = row_pattern.scan(/%\{([a-z_]+)\}/).flatten
|
126
|
-
result.map! { |element| send("format_#{element}".to_sym, row, lang) }
|
127
|
-
result.flatten.join
|
130
|
+
[format_comment(row, lang), format_key_value(row, lang)].compact.join
|
128
131
|
end
|
129
132
|
|
130
133
|
def format_comment(row, lang)
|
@@ -152,10 +155,10 @@ module Twine
|
|
152
155
|
end
|
153
156
|
|
154
157
|
def write_file(path, lang)
|
155
|
-
|
156
|
-
|
157
|
-
processed_strings = @output_processor.process(lang)
|
158
|
+
output_processor = Processors::OutputProcessor.new(@strings, @options)
|
159
|
+
processed_strings = output_processor.process(lang)
|
158
160
|
|
161
|
+
encoding = @options[:output_encoding] || 'UTF-8'
|
159
162
|
File.open(path, "w:#{encoding}") do |f|
|
160
163
|
f.puts format_file(processed_strings, lang)
|
161
164
|
end
|
@@ -169,7 +172,8 @@ module Twine
|
|
169
172
|
|
170
173
|
FileUtils.mkdir_p(output_path)
|
171
174
|
|
172
|
-
|
175
|
+
file_path = File.join(output_path, file_name)
|
176
|
+
write_file(file_path, lang)
|
173
177
|
end
|
174
178
|
else
|
175
179
|
language_written = false
|
@@ -182,7 +186,8 @@ module Twine
|
|
182
186
|
lang = determine_language_given_path(item)
|
183
187
|
next unless lang
|
184
188
|
|
185
|
-
|
189
|
+
file_path = File.join(item, file_name)
|
190
|
+
write_file(file_path, lang)
|
186
191
|
language_written = true
|
187
192
|
end
|
188
193
|
|
@@ -7,9 +7,6 @@ module Twine
|
|
7
7
|
class Android < Abstract
|
8
8
|
include Twine::Placeholders
|
9
9
|
|
10
|
-
FORMAT_NAME = 'android'
|
11
|
-
EXTENSION = '.xml'
|
12
|
-
DEFAULT_FILE_NAME = 'strings.xml'
|
13
10
|
LANG_CODES = Hash[
|
14
11
|
'zh' => 'zh-Hans',
|
15
12
|
'zh-rCN' => 'zh-Hans',
|
@@ -20,12 +17,20 @@ module Twine
|
|
20
17
|
# TODO: spanish
|
21
18
|
]
|
22
19
|
|
23
|
-
def
|
20
|
+
def format_name
|
21
|
+
'android'
|
22
|
+
end
|
23
|
+
|
24
|
+
def extension
|
25
|
+
'.xml'
|
26
|
+
end
|
27
|
+
|
28
|
+
def can_handle_directory?(path)
|
24
29
|
Dir.entries(path).any? { |item| /^values.*$/.match(item) }
|
25
30
|
end
|
26
31
|
|
27
32
|
def default_file_name
|
28
|
-
return
|
33
|
+
return 'strings.xml'
|
29
34
|
end
|
30
35
|
|
31
36
|
def determine_language_given_path(path)
|
@@ -135,3 +140,5 @@ module Twine
|
|
135
140
|
end
|
136
141
|
end
|
137
142
|
end
|
143
|
+
|
144
|
+
Twine::Formatters.formatters << Twine::Formatters::Android.new
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module Twine
|
2
2
|
module Formatters
|
3
3
|
class Apple < Abstract
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def format_name
|
5
|
+
'apple'
|
6
|
+
end
|
7
|
+
|
8
|
+
def extension
|
9
|
+
'.strings'
|
10
|
+
end
|
7
11
|
|
8
|
-
def
|
12
|
+
def can_handle_directory?(path)
|
9
13
|
Dir.entries(path).any? { |item| /^.+\.lproj$/.match(item) }
|
10
14
|
end
|
11
15
|
|
12
16
|
def default_file_name
|
13
|
-
return
|
17
|
+
return 'Localizable.strings'
|
14
18
|
end
|
15
19
|
|
16
20
|
def determine_language_given_path(path)
|
@@ -111,3 +115,5 @@ module Twine
|
|
111
115
|
end
|
112
116
|
end
|
113
117
|
end
|
118
|
+
|
119
|
+
Twine::Formatters.formatters << Twine::Formatters::Apple.new
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module Twine
|
2
2
|
module Formatters
|
3
3
|
class Django < Abstract
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def format_name
|
5
|
+
'django'
|
6
|
+
end
|
7
|
+
|
8
|
+
def extension
|
9
|
+
'.po'
|
10
|
+
end
|
7
11
|
|
8
|
-
def
|
9
|
-
|
12
|
+
def can_handle_directory?(path)
|
13
|
+
Dir.entries(path).any? { |item| /^.+\.po$/.match(item) }
|
10
14
|
end
|
11
15
|
|
12
16
|
def default_file_name
|
13
|
-
return
|
17
|
+
return 'strings.po'
|
14
18
|
end
|
15
19
|
|
16
20
|
def determine_language_given_path(path)
|
@@ -92,7 +96,9 @@ module Twine
|
|
92
96
|
|
93
97
|
def format_file(strings, lang)
|
94
98
|
@default_lang = strings.language_codes[0]
|
95
|
-
super
|
99
|
+
result = super
|
100
|
+
@default_lang = nil
|
101
|
+
result
|
96
102
|
end
|
97
103
|
|
98
104
|
def format_header(lang)
|
@@ -103,11 +109,11 @@ module Twine
|
|
103
109
|
"#--------- #{section.name} ---------#\n"
|
104
110
|
end
|
105
111
|
|
106
|
-
def
|
107
|
-
|
112
|
+
def format_row(row, lang)
|
113
|
+
[format_comment(row, lang), format_base_translation(row), format_key_value(row, lang)].compact.join
|
108
114
|
end
|
109
115
|
|
110
|
-
def format_base_translation(row
|
116
|
+
def format_base_translation(row)
|
111
117
|
base_translation = row.translations[@default_lang]
|
112
118
|
"# base translation: \"#{base_translation}\"\n" if base_translation
|
113
119
|
end
|
@@ -131,3 +137,5 @@ module Twine
|
|
131
137
|
end
|
132
138
|
end
|
133
139
|
end
|
140
|
+
|
141
|
+
Twine::Formatters.formatters << Twine::Formatters::Django.new
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module Twine
|
2
2
|
module Formatters
|
3
3
|
class Flash < Abstract
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def format_name
|
5
|
+
'flash'
|
6
|
+
end
|
7
|
+
|
8
|
+
def extension
|
9
|
+
'.properties'
|
10
|
+
end
|
7
11
|
|
8
|
-
def
|
12
|
+
def can_handle_directory?(path)
|
9
13
|
return false
|
10
14
|
end
|
11
15
|
|
12
16
|
def default_file_name
|
13
|
-
return
|
17
|
+
return 'resources.properties'
|
14
18
|
end
|
15
19
|
|
16
20
|
def determine_language_given_path(path)
|
@@ -93,3 +97,5 @@ module Twine
|
|
93
97
|
end
|
94
98
|
end
|
95
99
|
end
|
100
|
+
|
101
|
+
Twine::Formatters.formatters << Twine::Formatters::Flash.new
|
@@ -3,16 +3,20 @@
|
|
3
3
|
module Twine
|
4
4
|
module Formatters
|
5
5
|
class Gettext < Abstract
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def format_name
|
7
|
+
'gettext'
|
8
|
+
end
|
9
|
+
|
10
|
+
def extension
|
11
|
+
'.po'
|
12
|
+
end
|
9
13
|
|
10
|
-
def
|
14
|
+
def can_handle_directory?(path)
|
11
15
|
Dir.entries(path).any? { |item| /^.+\.po$/.match(item) }
|
12
16
|
end
|
13
17
|
|
14
18
|
def default_file_name
|
15
|
-
return
|
19
|
+
return 'strings.po'
|
16
20
|
end
|
17
21
|
|
18
22
|
def determine_language_given_path(path)
|
@@ -62,7 +66,9 @@ module Twine
|
|
62
66
|
|
63
67
|
def format_file(strings, lang)
|
64
68
|
@default_lang = strings.language_codes[0]
|
65
|
-
super
|
69
|
+
result = super
|
70
|
+
@default_lang = nil
|
71
|
+
result
|
66
72
|
end
|
67
73
|
|
68
74
|
def format_header(lang)
|
@@ -73,31 +79,32 @@ module Twine
|
|
73
79
|
"# SECTION: #{section.name}"
|
74
80
|
end
|
75
81
|
|
76
|
-
def
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
def format_row(row, lang)
|
81
|
-
return nil unless row.translated_string_for_lang(@default_lang)
|
82
|
-
|
83
|
-
super
|
82
|
+
def should_include_row(row, lang)
|
83
|
+
super and row.translated_string_for_lang(@default_lang)
|
84
84
|
end
|
85
85
|
|
86
86
|
def format_comment(row, lang)
|
87
87
|
"#. \"#{escape_quotes(row.comment)}\"\n" if row.comment
|
88
88
|
end
|
89
89
|
|
90
|
-
def
|
91
|
-
|
90
|
+
def format_key_value(row, lang)
|
91
|
+
value = row.translated_string_for_lang(lang)
|
92
|
+
[format_key(row.key.dup), format_base_translation(row), format_value(value.dup)].compact.join
|
93
|
+
end
|
94
|
+
|
95
|
+
def format_key(key)
|
96
|
+
"msgctxt \"#{key}\"\n"
|
92
97
|
end
|
93
98
|
|
94
|
-
def format_base_translation(row
|
99
|
+
def format_base_translation(row)
|
95
100
|
"msgid \"#{row.translations[@default_lang]}\"\n"
|
96
101
|
end
|
97
102
|
|
98
|
-
def format_value(
|
99
|
-
"msgstr \"#{
|
103
|
+
def format_value(value)
|
104
|
+
"msgstr \"#{value}\"\n"
|
100
105
|
end
|
101
106
|
end
|
102
107
|
end
|
103
108
|
end
|
109
|
+
|
110
|
+
Twine::Formatters.formatters << Twine::Formatters::Gettext.new
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module Twine
|
2
2
|
module Formatters
|
3
3
|
class JQuery < Abstract
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def format_name
|
5
|
+
'jquery'
|
6
|
+
end
|
7
|
+
|
8
|
+
def extension
|
9
|
+
'.json'
|
10
|
+
end
|
7
11
|
|
8
|
-
def
|
12
|
+
def can_handle_directory?(path)
|
9
13
|
Dir.entries(path).any? { |item| /^.+\.json$/.match(item) }
|
10
14
|
end
|
11
15
|
|
12
16
|
def default_file_name
|
13
|
-
return
|
17
|
+
return 'localize.json'
|
14
18
|
end
|
15
19
|
|
16
20
|
def determine_language_given_path(path)
|
@@ -71,15 +75,8 @@ module Twine
|
|
71
75
|
def format_value(value)
|
72
76
|
escape_quotes(value)
|
73
77
|
end
|
74
|
-
|
75
|
-
def write_file(path, lang)
|
76
|
-
begin
|
77
|
-
require "json"
|
78
|
-
rescue LoadError
|
79
|
-
raise Twine::Error.new "You must run 'gem install json' in order to read or write jquery-localize files."
|
80
|
-
end
|
81
|
-
super
|
82
|
-
end
|
83
78
|
end
|
84
79
|
end
|
85
80
|
end
|
81
|
+
|
82
|
+
Twine::Formatters.formatters << Twine::Formatters::JQuery.new
|
@@ -7,9 +7,6 @@ module Twine
|
|
7
7
|
class Tizen < Abstract
|
8
8
|
include Twine::Placeholders
|
9
9
|
|
10
|
-
FORMAT_NAME = 'tizen'
|
11
|
-
EXTENSION = '.xml'
|
12
|
-
DEFAULT_FILE_NAME = 'strings.xml'
|
13
10
|
LANG_CODES = Hash[
|
14
11
|
'eng-GB' => 'en',
|
15
12
|
'rus-RU' => 'ru',
|
@@ -22,39 +19,21 @@ module Twine
|
|
22
19
|
'por-PT' => 'pt',
|
23
20
|
'ukr-UA' => 'uk'
|
24
21
|
]
|
25
|
-
DEFAULT_LANG_CODES = Hash[
|
26
|
-
]
|
27
22
|
|
28
|
-
def
|
29
|
-
|
23
|
+
def format_name
|
24
|
+
'tizen'
|
30
25
|
end
|
31
26
|
|
32
|
-
def
|
33
|
-
|
27
|
+
def extension
|
28
|
+
'.xml'
|
34
29
|
end
|
35
30
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
end
|
31
|
+
def can_handle_directory?(path)
|
32
|
+
Dir.entries(path).any? { |item| /^values.*$/.match(item) }
|
33
|
+
end
|
40
34
|
|
41
|
-
|
42
|
-
|
43
|
-
if item == "." or item == ".."
|
44
|
-
next
|
45
|
-
end
|
46
|
-
item = File.join(path, item)
|
47
|
-
if !File.directory?(item)
|
48
|
-
lang = determine_language_given_path(item)
|
49
|
-
if lang
|
50
|
-
write_file(item, lang)
|
51
|
-
langs_written << lang
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
if langs_written.empty?
|
56
|
-
raise Twine::Error.new("Failed to genertate any files: No languages found at #{path}")
|
57
|
-
end
|
35
|
+
def default_file_name
|
36
|
+
return 'strings.xml'
|
58
37
|
end
|
59
38
|
|
60
39
|
def determine_language_given_path(path)
|
@@ -156,3 +135,5 @@ module Twine
|
|
156
135
|
end
|
157
136
|
end
|
158
137
|
end
|
138
|
+
|
139
|
+
Twine::Formatters.formatters << Twine::Formatters::Tizen.new
|
data/lib/twine/runner.rb
CHANGED
@@ -43,13 +43,17 @@ module Twine
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def generate_string_file
|
46
|
+
validate_strings_file if @options[:validate]
|
47
|
+
|
46
48
|
lang = nil
|
47
49
|
lang = @options[:languages][0] if @options[:languages]
|
48
50
|
|
49
|
-
|
51
|
+
write_string_file(@options[:output_path], lang)
|
50
52
|
end
|
51
53
|
|
52
54
|
def generate_all_string_files
|
55
|
+
validate_strings_file if @options[:validate]
|
56
|
+
|
53
57
|
if !File.directory?(@options[:output_path])
|
54
58
|
if @options[:create_folders]
|
55
59
|
FileUtils.mkdir_p(@options[:output_path])
|
@@ -58,13 +62,13 @@ module Twine
|
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
61
|
-
|
62
|
-
|
65
|
+
formatter_for_directory = find_formatter { |f| f.can_handle_directory?(@options[:output_path]) }
|
66
|
+
formatter = formatter_for_format(@options[:format]) || formatter_for_directory
|
67
|
+
|
68
|
+
unless formatter
|
63
69
|
raise Twine::Error.new "Could not determine format given the contents of #{@options[:output_path]}"
|
64
70
|
end
|
65
71
|
|
66
|
-
formatter = formatter_for_format(format)
|
67
|
-
|
68
72
|
formatter.write_all_files(@options[:output_path])
|
69
73
|
end
|
70
74
|
|
@@ -74,7 +78,7 @@ module Twine
|
|
74
78
|
lang = @options[:languages][0]
|
75
79
|
end
|
76
80
|
|
77
|
-
|
81
|
+
read_string_file(@options[:input_path], lang)
|
78
82
|
output_path = @options[:output_path] || @options[:strings_file]
|
79
83
|
write_strings_data(output_path)
|
80
84
|
end
|
@@ -87,7 +91,7 @@ module Twine
|
|
87
91
|
Dir.glob(File.join(@options[:input_path], "**/*")) do |item|
|
88
92
|
if File.file?(item)
|
89
93
|
begin
|
90
|
-
|
94
|
+
read_string_file(item)
|
91
95
|
rescue Twine::Error => e
|
92
96
|
Twine::stderr.puts "#{e.message}"
|
93
97
|
end
|
@@ -98,35 +102,9 @@ module Twine
|
|
98
102
|
write_strings_data(output_path)
|
99
103
|
end
|
100
104
|
|
101
|
-
def read_write_string_file(path, is_read, lang)
|
102
|
-
if is_read && !File.file?(path)
|
103
|
-
raise Twine::Error.new("File does not exist: #{path}")
|
104
|
-
end
|
105
|
-
|
106
|
-
format = @options[:format] || determine_format_given_path(path)
|
107
|
-
unless format
|
108
|
-
raise Twine::Error.new "Unable to determine format of #{path}"
|
109
|
-
end
|
110
|
-
|
111
|
-
formatter = formatter_for_format(format)
|
112
|
-
|
113
|
-
lang = lang || determine_language_given_path(path) || formatter.determine_language_given_path(path)
|
114
|
-
unless lang
|
115
|
-
raise Twine::Error.new "Unable to determine language for #{path}"
|
116
|
-
end
|
117
|
-
|
118
|
-
if !@strings.language_codes.include? lang
|
119
|
-
@strings.language_codes << lang
|
120
|
-
end
|
121
|
-
|
122
|
-
if is_read
|
123
|
-
formatter.read_file(path, lang)
|
124
|
-
else
|
125
|
-
formatter.write_file(path, lang)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
105
|
def generate_loc_drop
|
106
|
+
validate_strings_file if @options[:validate]
|
107
|
+
|
130
108
|
require_rubyzip
|
131
109
|
|
132
110
|
if File.file?(@options[:output_path])
|
@@ -140,7 +118,7 @@ module Twine
|
|
140
118
|
formatter = formatter_for_format(@options[:format])
|
141
119
|
@strings.language_codes.each do |lang|
|
142
120
|
if @options[:languages] == nil || @options[:languages].length == 0 || @options[:languages].include?(lang)
|
143
|
-
file_name = lang + formatter.
|
121
|
+
file_name = lang + formatter.extension
|
144
122
|
real_path = File.join(dir, file_name)
|
145
123
|
zip_path = File.join('Locales', file_name)
|
146
124
|
formatter.write_file(real_path, lang)
|
@@ -166,7 +144,7 @@ module Twine
|
|
166
144
|
FileUtils.mkdir_p(File.dirname(real_path))
|
167
145
|
zipfile.extract(entry.name, real_path)
|
168
146
|
begin
|
169
|
-
|
147
|
+
read_string_file(real_path)
|
170
148
|
rescue Twine::Error => e
|
171
149
|
Twine::stderr.puts "#{e.message}"
|
172
150
|
end
|
@@ -207,10 +185,12 @@ module Twine
|
|
207
185
|
errors << "Found duplicate string key(s):\n#{join_keys.call(duplicate_keys)}"
|
208
186
|
end
|
209
187
|
|
210
|
-
if
|
211
|
-
|
212
|
-
|
213
|
-
|
188
|
+
if @options[:pedantic]
|
189
|
+
if keys_without_tags.length == total_strings
|
190
|
+
errors << "None of your strings have tags."
|
191
|
+
elsif keys_without_tags.length > 0
|
192
|
+
errors << "Found strings without tags:\n#{join_keys.call(keys_without_tags)}"
|
193
|
+
end
|
214
194
|
end
|
215
195
|
|
216
196
|
unless invalid_keys.empty?
|
@@ -222,34 +202,64 @@ module Twine
|
|
222
202
|
Twine::stdout.puts "#{@options[:strings_file]} is valid."
|
223
203
|
end
|
224
204
|
|
205
|
+
private
|
206
|
+
|
207
|
+
def require_rubyzip
|
208
|
+
begin
|
209
|
+
require 'zip'
|
210
|
+
rescue LoadError
|
211
|
+
raise Twine::Error.new "You must run 'gem install rubyzip' in order to create or consume localization drops."
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
225
215
|
def determine_language_given_path(path)
|
226
216
|
code = File.basename(path, File.extname(path))
|
227
217
|
return code if @strings.language_codes.include? code
|
228
218
|
end
|
229
219
|
|
230
|
-
def
|
231
|
-
|
232
|
-
return formatter::FORMAT_NAME if formatter
|
220
|
+
def formatter_for_format(format)
|
221
|
+
find_formatter { |f| f.format_name == format }
|
233
222
|
end
|
234
223
|
|
235
|
-
def
|
236
|
-
formatter = Formatters.formatters.find
|
237
|
-
return
|
224
|
+
def find_formatter(&block)
|
225
|
+
formatter = Formatters.formatters.find &block
|
226
|
+
return nil unless formatter
|
227
|
+
formatter.strings = @strings
|
228
|
+
formatter.options = @options
|
229
|
+
formatter
|
238
230
|
end
|
239
231
|
|
240
|
-
def
|
241
|
-
|
242
|
-
|
232
|
+
def read_string_file(path, lang = nil)
|
233
|
+
unless File.file?(path)
|
234
|
+
raise Twine::Error.new("File does not exist: #{path}")
|
235
|
+
end
|
236
|
+
|
237
|
+
formatter, lang = prepare_read_write(path, lang)
|
238
|
+
|
239
|
+
formatter.read_file(path, lang)
|
243
240
|
end
|
244
241
|
|
245
|
-
|
242
|
+
def write_string_file(path, lang)
|
243
|
+
formatter, lang = prepare_read_write(path, lang)
|
244
|
+
formatter.write_file(path, lang)
|
245
|
+
end
|
246
246
|
|
247
|
-
def
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
247
|
+
def prepare_read_write(path, lang)
|
248
|
+
formatter_for_path = find_formatter { |f| f.extension == File.extname(path) }
|
249
|
+
formatter = formatter_for_format(@options[:format]) || formatter_for_path
|
250
|
+
|
251
|
+
unless formatter
|
252
|
+
raise Twine::Error.new "Unable to determine format of #{path}"
|
253
|
+
end
|
254
|
+
|
255
|
+
lang = lang || determine_language_given_path(path) || formatter.determine_language_given_path(path)
|
256
|
+
unless lang
|
257
|
+
raise Twine::Error.new "Unable to determine language for #{path}"
|
252
258
|
end
|
259
|
+
|
260
|
+
@strings.language_codes << lang unless @strings.language_codes.include? lang
|
261
|
+
|
262
|
+
return formatter, lang
|
253
263
|
end
|
254
264
|
end
|
255
265
|
end
|
data/lib/twine/version.rb
CHANGED
data/test/command_test_case.rb
CHANGED
@@ -5,8 +5,10 @@ class CommandTestCase < TwineTestCase
|
|
5
5
|
strings = Twine::StringsFile.new
|
6
6
|
strings.language_codes.concat KNOWN_LANGUAGES
|
7
7
|
|
8
|
-
formatter = formatter_class.new
|
9
|
-
|
8
|
+
formatter = formatter_class.new
|
9
|
+
formatter.strings = strings
|
10
|
+
Twine::Formatters.formatters.clear
|
11
|
+
Twine::Formatters.formatters << formatter
|
10
12
|
formatter
|
11
13
|
end
|
12
14
|
end
|
@@ -12,7 +12,8 @@ class TestAbstractFormatter < TwineTestCase
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
@formatter = Twine::Formatters::Abstract.new
|
15
|
+
@formatter = Twine::Formatters::Abstract.new
|
16
|
+
@formatter.strings = @strings
|
16
17
|
end
|
17
18
|
|
18
19
|
def test_set_translation_updates_existing_value
|
@@ -46,7 +47,9 @@ class TestAbstractFormatter < TwineTestCase
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def test_set_translation_consume_all_adds_new_key
|
49
|
-
formatter = Twine::Formatters::Abstract.new
|
50
|
+
formatter = Twine::Formatters::Abstract.new
|
51
|
+
formatter.strings = @strings
|
52
|
+
formatter.options = { consume_all: true }
|
50
53
|
formatter.set_translation_for_key 'new-key', 'en', 'new-key-english'
|
51
54
|
|
52
55
|
assert_equal 'new-key-english', @strings.strings_map['new-key'].translations['en']
|
@@ -54,14 +57,18 @@ class TestAbstractFormatter < TwineTestCase
|
|
54
57
|
|
55
58
|
def test_set_translation_consume_all_adds_tags
|
56
59
|
random_tag = SecureRandom.uuid
|
57
|
-
formatter = Twine::Formatters::Abstract.new
|
60
|
+
formatter = Twine::Formatters::Abstract.new
|
61
|
+
formatter.strings = @strings
|
62
|
+
formatter.options = { consume_all: true, tags: [random_tag] }
|
58
63
|
formatter.set_translation_for_key 'new-key', 'en', 'new-key-english'
|
59
64
|
|
60
65
|
assert_equal [random_tag], @strings.strings_map['new-key'].tags
|
61
66
|
end
|
62
67
|
|
63
68
|
def test_set_translation_adds_new_keys_to_category_uncategoriezed
|
64
|
-
formatter = Twine::Formatters::Abstract.new
|
69
|
+
formatter = Twine::Formatters::Abstract.new
|
70
|
+
formatter.strings = @strings
|
71
|
+
formatter.options = { consume_all: true }
|
65
72
|
formatter.set_translation_for_key 'new-key', 'en', 'new-key-english'
|
66
73
|
|
67
74
|
assert_equal 'Uncategorized', @strings.sections[0].name
|
@@ -80,7 +87,8 @@ class TestAbstractFormatter < TwineTestCase
|
|
80
87
|
end
|
81
88
|
end
|
82
89
|
|
83
|
-
@formatter = Twine::Formatters::Abstract.new
|
90
|
+
@formatter = Twine::Formatters::Abstract.new
|
91
|
+
@formatter.strings = @strings
|
84
92
|
end
|
85
93
|
|
86
94
|
def test_set_translation_does_not_add_unchanged_translation
|
@@ -108,14 +116,17 @@ class TestAbstractFormatter < TwineTestCase
|
|
108
116
|
end
|
109
117
|
|
110
118
|
def test_set_comment_for_key_does_not_update_comment
|
111
|
-
formatter = Twine::Formatters::Abstract.new
|
119
|
+
formatter = Twine::Formatters::Abstract.new
|
120
|
+
formatter.strings = @strings
|
112
121
|
formatter.set_comment_for_key('key', 'comment')
|
113
122
|
|
114
123
|
assert_nil formatter.strings.strings_map['key'].comment
|
115
124
|
end
|
116
125
|
|
117
126
|
def test_set_comment_for_key_updates_comment_with_update_comments
|
118
|
-
formatter = Twine::Formatters::Abstract.new
|
127
|
+
formatter = Twine::Formatters::Abstract.new
|
128
|
+
formatter.strings = @strings
|
129
|
+
formatter.options = { consume_comments: true }
|
119
130
|
formatter.set_comment_for_key('key', 'comment')
|
120
131
|
|
121
132
|
assert_equal 'comment', formatter.strings.strings_map['key'].comment
|
@@ -133,7 +144,9 @@ class TestAbstractFormatter < TwineTestCase
|
|
133
144
|
end
|
134
145
|
end
|
135
146
|
|
136
|
-
@formatter = Twine::Formatters::Abstract.new
|
147
|
+
@formatter = Twine::Formatters::Abstract.new
|
148
|
+
@formatter.strings = @strings
|
149
|
+
@formatter.options = { consume_comments: true }
|
137
150
|
end
|
138
151
|
|
139
152
|
def test_set_comment_does_not_add_unchanged_comment
|
data/test/test_cli.rb
CHANGED
@@ -21,6 +21,11 @@ class CLITestCase < TwineTestCase
|
|
21
21
|
assert_equal @strings_file_path, @options[:strings_file]
|
22
22
|
end
|
23
23
|
|
24
|
+
def test_pedantic
|
25
|
+
parse "validate-strings-file #{@strings_file_path} --pedantic"
|
26
|
+
assert @options[:pedantic]
|
27
|
+
end
|
28
|
+
|
24
29
|
def test_missing_parameter
|
25
30
|
assert_raises Twine::Error do
|
26
31
|
parse 'validate-strings-file'
|
@@ -49,6 +54,11 @@ class CLITestCase < TwineTestCase
|
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
57
|
+
def test_validate
|
58
|
+
parse "generate-string-file #{@strings_file_path} #{@output_path} --validate"
|
59
|
+
assert @options[:validate]
|
60
|
+
end
|
61
|
+
|
52
62
|
def test_extra_parameter
|
53
63
|
assert_raises Twine::Error do
|
54
64
|
parse 'generate-string-file strings output extra'
|
@@ -77,6 +87,11 @@ class CLITestCase < TwineTestCase
|
|
77
87
|
end
|
78
88
|
end
|
79
89
|
|
90
|
+
def test_validate
|
91
|
+
parse "generate-all-string-files #{@strings_file_path} #{@output_dir} --validate"
|
92
|
+
assert @options[:validate]
|
93
|
+
end
|
94
|
+
|
80
95
|
def test_extra_parameter
|
81
96
|
assert_raises Twine::Error do
|
82
97
|
parse "generate-all-string-files strings output extra"
|
@@ -149,6 +164,11 @@ class CLITestCase < TwineTestCase
|
|
149
164
|
end
|
150
165
|
end
|
151
166
|
|
167
|
+
def test_validate
|
168
|
+
parse "generate-loc-drop #{@strings_file_path} #{@output_path} --format apple --validate"
|
169
|
+
assert @options[:validate]
|
170
|
+
end
|
171
|
+
|
152
172
|
def test_extra_parameter
|
153
173
|
assert_raises Twine::Error do
|
154
174
|
parse "generate-loc-drop strings output extra --format apple"
|
@@ -246,13 +266,13 @@ class CLITestCase < TwineTestCase
|
|
246
266
|
end
|
247
267
|
|
248
268
|
def test_format
|
249
|
-
random_format = Twine::Formatters.formatters.sample
|
269
|
+
random_format = Twine::Formatters.formatters.sample.format_name
|
250
270
|
parse_with "--format #{random_format}"
|
251
271
|
assert_equal random_format, @options[:format]
|
252
272
|
end
|
253
273
|
|
254
274
|
def test_format_ignores_case
|
255
|
-
random_format = Twine::Formatters.formatters.sample
|
275
|
+
random_format = Twine::Formatters.formatters.sample.format_name
|
256
276
|
parse_with "--format #{random_format.upcase}"
|
257
277
|
assert_equal random_format, @options[:format]
|
258
278
|
end
|
data/test/test_formatters.rb
CHANGED
@@ -17,7 +17,9 @@ class FormatterTest < TwineTestCase
|
|
17
17
|
end
|
18
18
|
|
19
19
|
@strings = Twine::StringsFile.new
|
20
|
-
@formatter = formatter_class.new
|
20
|
+
@formatter = formatter_class.new
|
21
|
+
@formatter.strings = @strings
|
22
|
+
@formatter.options = { consume_all: true, consume_comments: true }
|
21
23
|
end
|
22
24
|
|
23
25
|
def assert_translations_read_correctly
|
@@ -66,7 +68,8 @@ class TestAndroidFormatter < FormatterTest
|
|
66
68
|
end
|
67
69
|
|
68
70
|
def test_write_file_output_format
|
69
|
-
formatter = Twine::Formatters::Android.new
|
71
|
+
formatter = Twine::Formatters::Android.new
|
72
|
+
formatter.strings = @twine_file
|
70
73
|
formatter.write_file @output_path, 'en'
|
71
74
|
assert_equal content('formatter_android.xml'), output_content
|
72
75
|
end
|
@@ -111,7 +114,8 @@ class TestAppleFormatter < FormatterTest
|
|
111
114
|
end
|
112
115
|
|
113
116
|
def test_write_file_output_format
|
114
|
-
formatter = Twine::Formatters::Apple.new
|
117
|
+
formatter = Twine::Formatters::Apple.new
|
118
|
+
formatter.strings = @twine_file
|
115
119
|
formatter.write_file @output_path, 'en'
|
116
120
|
assert_equal content('formatter_apple.strings'), output_content
|
117
121
|
end
|
@@ -142,7 +146,8 @@ class TestJQueryFormatter < FormatterTest
|
|
142
146
|
end
|
143
147
|
|
144
148
|
def test_write_file_output_format
|
145
|
-
formatter = Twine::Formatters::JQuery.new
|
149
|
+
formatter = Twine::Formatters::JQuery.new
|
150
|
+
formatter.strings = @twine_file
|
146
151
|
formatter.write_file @output_path, 'en'
|
147
152
|
assert_equal content('formatter_jquery.json'), output_content
|
148
153
|
end
|
@@ -171,7 +176,8 @@ class TestGettextFormatter < FormatterTest
|
|
171
176
|
end
|
172
177
|
|
173
178
|
def test_write_file_output_format
|
174
|
-
formatter = Twine::Formatters::Gettext.new
|
179
|
+
formatter = Twine::Formatters::Gettext.new
|
180
|
+
formatter.strings = @twine_file
|
175
181
|
formatter.write_file @output_path, 'en'
|
176
182
|
assert_equal content('formatter_gettext.po'), output_content
|
177
183
|
end
|
@@ -192,7 +198,8 @@ class TestTizenFormatter < FormatterTest
|
|
192
198
|
end
|
193
199
|
|
194
200
|
def test_write_file_output_format
|
195
|
-
formatter = Twine::Formatters::Tizen.new
|
201
|
+
formatter = Twine::Formatters::Tizen.new
|
202
|
+
formatter.strings = @twine_file
|
196
203
|
formatter.write_file @output_path, 'en'
|
197
204
|
assert_equal content('formatter_tizen.xml'), output_content
|
198
205
|
end
|
@@ -211,7 +218,8 @@ class TestDjangoFormatter < FormatterTest
|
|
211
218
|
end
|
212
219
|
|
213
220
|
def test_write_file_output_format
|
214
|
-
formatter = Twine::Formatters::Django.new
|
221
|
+
formatter = Twine::Formatters::Django.new
|
222
|
+
formatter.strings = @twine_file
|
215
223
|
formatter.write_file @output_path, 'en'
|
216
224
|
assert_equal content('formatter_django.po'), output_content
|
217
225
|
end
|
@@ -229,7 +237,8 @@ class TestFlashFormatter < FormatterTest
|
|
229
237
|
end
|
230
238
|
|
231
239
|
def test_write_file_output_format
|
232
|
-
formatter = Twine::Formatters::Flash.new
|
240
|
+
formatter = Twine::Formatters::Flash.new
|
241
|
+
formatter.strings = @twine_file
|
233
242
|
formatter.write_file @output_path, 'en'
|
234
243
|
assert_equal content('formatter_flash.properties'), output_content
|
235
244
|
end
|
@@ -8,13 +8,13 @@ class TestGenerateAllStringFiles < CommandTestCase
|
|
8
8
|
options[:format] = 'apple'
|
9
9
|
options[:create_folders] = create_folders
|
10
10
|
|
11
|
-
|
11
|
+
twine_file = build_twine_file 'en', 'es' do
|
12
12
|
add_section 'Section' do
|
13
13
|
add_row key: 'value'
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
Twine::Runner.new(options,
|
17
|
+
Twine::Runner.new(options, twine_file)
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_fails_if_output_folder_does_not_exist
|
@@ -41,4 +41,36 @@ class TestGenerateAllStringFiles < CommandTestCase
|
|
41
41
|
assert File.exists?(File.join(@output_dir, 'es.lproj')), "language folder 'es.lproj' should be created"
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
class TestDeliberate < CommandTestCase
|
46
|
+
def new_runner(validate)
|
47
|
+
Dir.mkdir File.join @output_dir, 'values-en'
|
48
|
+
|
49
|
+
options = {}
|
50
|
+
options[:output_path] = @output_dir
|
51
|
+
options[:format] = 'android'
|
52
|
+
options[:validate] = validate
|
53
|
+
|
54
|
+
twine_file = build_twine_file 'en' do
|
55
|
+
add_section 'Section' do
|
56
|
+
add_row key: 'value'
|
57
|
+
add_row key: 'value'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Twine::Runner.new(options, twine_file)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_does_not_validate_strings_file
|
65
|
+
prepare_mock_formatter Twine::Formatters::Android
|
66
|
+
|
67
|
+
new_runner(false).generate_all_string_files
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_validates_strings_file_if_validate
|
71
|
+
assert_raises Twine::Error do
|
72
|
+
new_runner(true).generate_all_string_files
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
44
76
|
end
|
@@ -41,4 +41,34 @@ class TestGenerateLocDrop < CommandTestCase
|
|
41
41
|
|
42
42
|
@runner.generate_loc_drop
|
43
43
|
end
|
44
|
+
|
45
|
+
class TestDeliberate < CommandTestCase
|
46
|
+
def new_runner(validate)
|
47
|
+
options = {}
|
48
|
+
options[:output_path] = @output_path
|
49
|
+
options[:format] = 'android'
|
50
|
+
options[:validate] = validate
|
51
|
+
|
52
|
+
twine_file = build_twine_file 'en' do
|
53
|
+
add_section 'Section' do
|
54
|
+
add_row key: 'value'
|
55
|
+
add_row key: 'value'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
Twine::Runner.new(options, twine_file)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_does_not_validate_strings_file
|
63
|
+
prepare_mock_formatter Twine::Formatters::Android
|
64
|
+
|
65
|
+
new_runner(false).generate_loc_drop
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_validates_strings_file_if_validate
|
69
|
+
assert_raises Twine::Error do
|
70
|
+
new_runner(true).generate_loc_drop
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
44
74
|
end
|
@@ -6,10 +6,10 @@ class TestGenerateStringFile < CommandTestCase
|
|
6
6
|
options[:output_path] = File.join(@output_dir, file) if file
|
7
7
|
options[:languages] = language if language
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
strings = Twine::StringsFile.new
|
10
|
+
strings.language_codes.concat KNOWN_LANGUAGES
|
11
11
|
|
12
|
-
Twine::Runner.new(options,
|
12
|
+
Twine::Runner.new(options, strings)
|
13
13
|
end
|
14
14
|
|
15
15
|
def prepare_mock_write_file_formatter(formatter_class)
|
@@ -48,4 +48,35 @@ class TestGenerateStringFile < CommandTestCase
|
|
48
48
|
|
49
49
|
new_runner(nil, "#{random_language}.xml").generate_string_file
|
50
50
|
end
|
51
|
+
|
52
|
+
class TestDeliberate < CommandTestCase
|
53
|
+
def new_runner(validate)
|
54
|
+
options = {}
|
55
|
+
options[:output_path] = @output_path
|
56
|
+
options[:languages] = ['en']
|
57
|
+
options[:format] = 'android'
|
58
|
+
options[:validate] = validate
|
59
|
+
|
60
|
+
twine_file = build_twine_file 'en' do
|
61
|
+
add_section 'Section' do
|
62
|
+
add_row key: 'value'
|
63
|
+
add_row key: 'value'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
Twine::Runner.new(options, twine_file)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_does_not_validate_strings_file
|
71
|
+
prepare_mock_formatter Twine::Formatters::Android
|
72
|
+
|
73
|
+
new_runner(false).generate_string_file
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_validates_strings_file_if_validate
|
77
|
+
assert_raises Twine::Error do
|
78
|
+
new_runner(true).generate_string_file
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
51
82
|
end
|
@@ -37,19 +37,25 @@ class TestValidateStringsFile < CommandTestCase
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
random_row.
|
40
|
+
def test_reports_invalid_characters_in_keys
|
41
|
+
random_row.key[0] = "!?;:,^`´'\"\\|/(){}[]~-+*=#$%".chars.to_a.sample
|
42
42
|
|
43
43
|
assert_raises Twine::Error do
|
44
44
|
Twine::Runner.new(@options, @twine_file).validate_strings_file
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
def
|
49
|
-
random_row.
|
48
|
+
def test_does_not_reports_missing_tags_by_default
|
49
|
+
random_row.tags.clear
|
50
|
+
|
51
|
+
Twine::Runner.new(@options, @twine_file).validate_strings_file
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_reports_missing_tags
|
55
|
+
random_row.tags.clear
|
50
56
|
|
51
57
|
assert_raises Twine::Error do
|
52
|
-
Twine::Runner.new(@options, @twine_file).validate_strings_file
|
58
|
+
Twine::Runner.new(@options.merge(pedantic: true), @twine_file).validate_strings_file
|
53
59
|
end
|
54
60
|
end
|
55
61
|
end
|
data/test/twine_test_case.rb
CHANGED
@@ -15,12 +15,17 @@ class TwineTestCase < Minitest::Test
|
|
15
15
|
super
|
16
16
|
Twine::stdout = StringIO.new
|
17
17
|
Twine::stderr = StringIO.new
|
18
|
+
|
19
|
+
@formatters = Twine::Formatters.formatters.dup
|
20
|
+
|
18
21
|
@output_dir = Dir.mktmpdir
|
19
22
|
@output_path = File.join @output_dir, SecureRandom.uuid
|
20
23
|
end
|
21
24
|
|
22
25
|
def teardown
|
23
26
|
FileUtils.remove_entry_secure @output_dir if File.exists? @output_dir
|
27
|
+
Twine::Formatters.formatters.clear
|
28
|
+
Twine::Formatters.formatters.concat @formatters
|
24
29
|
super
|
25
30
|
end
|
26
31
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastian Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -150,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
150
150
|
requirements:
|
151
151
|
- - ">="
|
152
152
|
- !ruby/object:Gem::Version
|
153
|
-
version:
|
153
|
+
version: '2.0'
|
154
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
155
|
requirements:
|
156
156
|
- - ">="
|