twine 0.5.0 → 0.6.0
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/README.md +25 -0
- data/bin/twine +1 -2
- data/lib/twine.rb +1 -0
- data/lib/twine/cli.rb +2 -2
- data/lib/twine/formatters.rb +19 -2
- data/lib/twine/formatters/abstract.rb +7 -2
- data/lib/twine/formatters/android.rb +3 -0
- data/lib/twine/formatters/jquery.rb +10 -19
- data/lib/twine/formatters/tizen.rb +175 -0
- data/lib/twine/plugin.rb +62 -0
- data/lib/twine/runner.rb +5 -3
- data/lib/twine/version.rb +1 -1
- data/test/fixtures/en-1.json +0 -7
- data/test/fixtures/en-3.xml +8 -0
- data/test/fixtures/test-json-line-breaks/consumed.txt +5 -0
- data/test/fixtures/test-json-line-breaks/generated.json +3 -0
- data/test/fixtures/test-json-line-breaks/line-breaks.json +3 -0
- data/test/fixtures/test-json-line-breaks/line-breaks.txt +4 -0
- data/test/fixtures/test-output-10.txt +9 -0
- data/test/fixtures/test-output-11.txt +9 -0
- data/test/fixtures/test-output-12.txt +12 -0
- data/test/fixtures/test-output-5.txt +1 -8
- data/test/twine_test.rb +40 -0
- metadata +27 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c52c16544077b748fb773dd7cd3f8d7f88172eeb
|
4
|
+
data.tar.gz: a4db219ebbef41d69c00a59e46d09971be26ba4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18423f5df5e0feda3ebd2e5e74c65ccb1bea506022ec79ee0d180f609e7acb2402348e1c37f78e02e00eee02933e6f6ba0f308b23e846d7e5e4e8896ad49b9c3
|
7
|
+
data.tar.gz: 010dca262cae3a0766d99d5a34aede2c05dba4ad5489d03c4798808cea3902fe3c5c443302e38712af26be12c3f8dedc442f3a25da2d483fc00adce9f5c36b4a
|
data/README.md
CHANGED
@@ -77,6 +77,7 @@ Twine currently supports the following formats for outputting strings:
|
|
77
77
|
* [Gettext PO Files][gettextpo] (format: gettext)
|
78
78
|
* [jquery-localize Language Files][jquerylocalize] (format: jquery)
|
79
79
|
* [Django PO Files][djangopo] (format: django)
|
80
|
+
* [Tizen String Resources][tizen] (format: tizen)
|
80
81
|
|
81
82
|
If you would like to enable twine to create language files in another format, create an appropriate formatter in `lib/twine/formatters`.
|
82
83
|
|
@@ -163,6 +164,28 @@ Now, whenever you build your application, Xcode will automatically invoke Twine
|
|
163
164
|
* [Twine TextMate 2 Bundle](https://github.com/mobiata/twine.tmbundle) — This [TextMate 2](https://github.com/textmate/textmate) bundle will make it easier for you to work with Twine strings files. In particular, it lets you use code folding to easily collapse and expand both strings and sections.
|
164
165
|
* [twine_ui](https://github.com/Daij-Djan/twine_ui) — A user interface for Twine written by [Dominik Pich](https://github.com/Daij-Djan/). Consider using this if you would prefer to use Twine without dropping to a command line.
|
165
166
|
|
167
|
+
## Plugin Support
|
168
|
+
|
169
|
+
Twine supports a basic plugin infrastructure, allowing third-party code to provide support for additional formatters. Twine will read a yaml config file specifying which plugins to load from three locations.
|
170
|
+
|
171
|
+
0. `./twine.yml` The current working directory
|
172
|
+
0. `~/.twine` The home directory
|
173
|
+
0. `/etc/twine.yml` The etc directory
|
174
|
+
|
175
|
+
Plugins are specified as values for the `gems` key. The following is an example config:
|
176
|
+
|
177
|
+
```
|
178
|
+
gems: appium_twine
|
179
|
+
```
|
180
|
+
|
181
|
+
Multiple gems can also be specfied in the yaml file.
|
182
|
+
|
183
|
+
```
|
184
|
+
gems: [appium_twine, some_other_plugin]
|
185
|
+
```
|
186
|
+
|
187
|
+
[appium_twine](https://github.com/appium/appium_twine) is a sample plugin used to provide a C# formatter.
|
188
|
+
|
166
189
|
## Contributors
|
167
190
|
|
168
191
|
Many thanks to all of the contributors to the Twine project, including:
|
@@ -174,6 +197,7 @@ Many thanks to all of the contributors to the Twine project, including:
|
|
174
197
|
* [Kevin Wood](https://github.com/kwood)
|
175
198
|
* [Mohammad Hejazi](https://github.com/MohammadHejazi)
|
176
199
|
* [Robert Guo](http://www.robertguo.me/)
|
200
|
+
* [Sergey Pisarchik](https://github.com/SergeyPisarchik)
|
177
201
|
* [Shai Shamir](https://github.com/pichirichi)
|
178
202
|
|
179
203
|
|
@@ -185,3 +209,4 @@ Many thanks to all of the contributors to the Twine project, including:
|
|
185
209
|
[gettextpo]: http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/PO-Files.html
|
186
210
|
[jquerylocalize]: https://github.com/coderifous/jquery-localize
|
187
211
|
[djangopo]: https://docs.djangoproject.com/en/dev/topics/i18n/translation/
|
212
|
+
[tizen]: https://developer.tizen.org/documentation/articles/localization
|
data/bin/twine
CHANGED
data/lib/twine.rb
CHANGED
data/lib/twine/cli.rb
CHANGED
@@ -45,7 +45,7 @@ module Twine
|
|
45
45
|
@options[:untagged] = true
|
46
46
|
end
|
47
47
|
formats = []
|
48
|
-
Formatters
|
48
|
+
Formatters.formatters.each do |formatter|
|
49
49
|
formats << formatter::FORMAT_NAME
|
50
50
|
end
|
51
51
|
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|
|
@@ -93,7 +93,7 @@ module Twine
|
|
93
93
|
opts.separator '> twine generate-string-file strings.txt ko.xml --tags FT'
|
94
94
|
opts.separator '> twine generate-all-string-files strings.txt Resources/Locales/ --tags FT,FB'
|
95
95
|
opts.separator '> twine consume-string-file strings.txt ja.strings'
|
96
|
-
opts.separator '> twine consume-all-string-files strings.txt Resources/Locales/ --developer-language en'
|
96
|
+
opts.separator '> twine consume-all-string-files strings.txt Resources/Locales/ --developer-language en --tags DefaultTag1,DefaultTag2'
|
97
97
|
opts.separator '> twine generate-loc-drop strings.txt LocDrop5.zip --tags FT,FB --format android --lang de,en,en-GB,ja,ko'
|
98
98
|
opts.separator '> twine consume-loc-drop strings.txt LocDrop5.zip'
|
99
99
|
opts.separator '> twine generate-report strings.txt'
|
data/lib/twine/formatters.rb
CHANGED
@@ -5,9 +5,26 @@ require 'twine/formatters/flash'
|
|
5
5
|
require 'twine/formatters/gettext'
|
6
6
|
require 'twine/formatters/jquery'
|
7
7
|
require 'twine/formatters/django'
|
8
|
+
require 'twine/formatters/tizen'
|
8
9
|
|
9
10
|
module Twine
|
10
11
|
module Formatters
|
11
|
-
|
12
|
+
@formatters = [Formatters::Apple, Formatters::Android, Formatters::Gettext, Formatters::JQuery, Formatters::Flash, Formatters::Django, Formatters::Tizen]
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_reader :formatters
|
16
|
+
|
17
|
+
###
|
18
|
+
# registers a new formatter
|
19
|
+
#
|
20
|
+
# formatter_class - the class of the formatter to register
|
21
|
+
#
|
22
|
+
# returns array of active formatters
|
23
|
+
#
|
24
|
+
def register_formatter formatter_class
|
25
|
+
raise "#{formatter_class} already registered" if @formatters.include? formatter_class
|
26
|
+
@formatters << formatter_class
|
27
|
+
end
|
28
|
+
end
|
12
29
|
end
|
13
|
-
end
|
30
|
+
end
|
@@ -66,7 +66,7 @@ module Twine
|
|
66
66
|
return str
|
67
67
|
end
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def set_translation_for_key(key, lang, value)
|
71
71
|
if @strings.strings_map.include?(key)
|
72
72
|
@strings.strings_map[key].translations[lang] = value
|
@@ -80,6 +80,11 @@ module Twine
|
|
80
80
|
end
|
81
81
|
current_row = StringsRow.new(key)
|
82
82
|
current_section.rows << current_row
|
83
|
+
|
84
|
+
if @options[:tags] && @options[:tags].length > 0
|
85
|
+
current_row.tags = @options[:tags]
|
86
|
+
end
|
87
|
+
|
83
88
|
@strings.strings_map[key] = current_row
|
84
89
|
@strings.strings_map[key].translations[lang] = value
|
85
90
|
else
|
@@ -133,7 +138,7 @@ module Twine
|
|
133
138
|
end
|
134
139
|
end
|
135
140
|
if langs_written.empty?
|
136
|
-
raise Twine::Error.new("Failed to
|
141
|
+
raise Twine::Error.new("Failed to generate any files: No languages found at #{path}")
|
137
142
|
end
|
138
143
|
end
|
139
144
|
end
|
@@ -71,6 +71,7 @@ module Twine
|
|
71
71
|
value.gsub!('\\\'', '\'')
|
72
72
|
value.gsub!('\\"', '"')
|
73
73
|
value = iosify_substitutions(value)
|
74
|
+
value.gsub!(/(\\u0020)*|(\\u0020)*\z/) { |spaces| ' ' * (spaces.length / 6) }
|
74
75
|
else
|
75
76
|
value = ""
|
76
77
|
end
|
@@ -129,6 +130,8 @@ module Twine
|
|
129
130
|
value = CGI.escapeHTML(value)
|
130
131
|
# 3) fix substitutions (e.g. %s/%@)
|
131
132
|
value = androidify_substitutions(value)
|
133
|
+
# 4) replace beginning and end spaces with \0020. Otherwise Android strips them.
|
134
|
+
value.gsub!(/\A *| *\z/) { |spaces| '\u0020' * spaces.length }
|
132
135
|
|
133
136
|
comment = row.comment
|
134
137
|
if comment
|
@@ -35,6 +35,7 @@ module Twine
|
|
35
35
|
open(path) do |io|
|
36
36
|
json = JSON.load(io)
|
37
37
|
json.each do |key, value|
|
38
|
+
value.gsub!("\n","\\n")
|
38
39
|
set_translation_for_key(key, lang, value)
|
39
40
|
end
|
40
41
|
end
|
@@ -47,21 +48,22 @@ module Twine
|
|
47
48
|
raise Twine::Error.new "You must run 'gem install json' in order to read or write jquery-localize files."
|
48
49
|
end
|
49
50
|
|
51
|
+
printed_string = false
|
50
52
|
default_lang = @strings.language_codes[0]
|
51
53
|
encoding = @options[:output_encoding] || 'UTF-8'
|
52
54
|
File.open(path, "w:#{encoding}") do |f|
|
53
|
-
f.
|
54
|
-
f.puts "{"
|
55
|
+
f.print "{"
|
55
56
|
|
56
57
|
@strings.sections.each_with_index do |section, si|
|
57
58
|
printed_section = false
|
58
59
|
section.rows.each_with_index do |row, ri|
|
59
60
|
if row.matches_tags?(@options[:tags], @options[:untagged])
|
61
|
+
if printed_string
|
62
|
+
f.print ",\n"
|
63
|
+
end
|
64
|
+
|
60
65
|
if !printed_section
|
61
|
-
f.
|
62
|
-
if section.name && section.name.length > 0
|
63
|
-
f.puts "/* #{section.name} */"
|
64
|
-
end
|
66
|
+
f.print "\n"
|
65
67
|
printed_section = true
|
66
68
|
end
|
67
69
|
|
@@ -71,22 +73,11 @@ module Twine
|
|
71
73
|
value = row.translated_string_for_lang(lang, default_lang)
|
72
74
|
value = value.gsub('"', '\\\\"')
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
comment = comment.gsub('*/', '* /')
|
77
|
-
end
|
78
|
-
|
79
|
-
f.print "\"#{key}\":\"#{value}\","
|
80
|
-
|
81
|
-
if comment && comment.length > 0
|
82
|
-
f.print " /* #{comment} */\n"
|
83
|
-
else
|
84
|
-
f.print "\n"
|
85
|
-
end
|
76
|
+
f.print "\"#{key}\":\"#{value}\""
|
77
|
+
printed_string = true
|
86
78
|
end
|
87
79
|
end
|
88
80
|
end
|
89
|
-
f.seek(-2, IO::SEEK_CUR)
|
90
81
|
f.puts "\n}"
|
91
82
|
|
92
83
|
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'cgi'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
module Twine
|
6
|
+
module Formatters
|
7
|
+
class Tizen < Abstract
|
8
|
+
FORMAT_NAME = 'tizen'
|
9
|
+
EXTENSION = '.xml'
|
10
|
+
DEFAULT_FILE_NAME = 'strings.xml'
|
11
|
+
LANG_CODES = Hash[
|
12
|
+
'eng-GB' => 'en',
|
13
|
+
'rus-RU' => 'ru',
|
14
|
+
'fra-FR' => 'fr',
|
15
|
+
'deu-DE' => 'de',
|
16
|
+
'spa-ES' => 'es',
|
17
|
+
'ita-IT' => 'it',
|
18
|
+
'ces-CZ' => 'cs',
|
19
|
+
'pol-PL' => 'pl',
|
20
|
+
'por-PT' => 'pt',
|
21
|
+
'ukr-UA' => 'uk'
|
22
|
+
]
|
23
|
+
DEFAULT_LANG_CODES = Hash[
|
24
|
+
]
|
25
|
+
|
26
|
+
def self.can_handle_directory?(path)
|
27
|
+
Dir.entries(path).any? { |item| /^values.*$/.match(item) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def default_file_name
|
31
|
+
return DEFAULT_FILE_NAME
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_all_files(path)
|
35
|
+
if !File.directory?(path)
|
36
|
+
raise Twine::Error.new("Directory does not exist: #{path}")
|
37
|
+
end
|
38
|
+
|
39
|
+
langs_written = []
|
40
|
+
Dir.foreach(path) do |item|
|
41
|
+
if item == "." or item == ".."
|
42
|
+
next
|
43
|
+
end
|
44
|
+
item = File.join(path, item)
|
45
|
+
if !File.directory?(item)
|
46
|
+
lang = determine_language_given_path(item)
|
47
|
+
if lang
|
48
|
+
write_file(item, lang)
|
49
|
+
langs_written << lang
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
if langs_written.empty?
|
54
|
+
raise Twine::Error.new("Failed to genertate any files: No languages found at #{path}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def determine_language_given_path(path)
|
59
|
+
path_arr = path.split(File::SEPARATOR)
|
60
|
+
path_arr.each do |segment|
|
61
|
+
match = /^(.*-.*)\.xml$/.match(segment)
|
62
|
+
if match
|
63
|
+
lang = match[1]
|
64
|
+
lang = LANG_CODES.fetch(lang, nil)
|
65
|
+
return lang
|
66
|
+
end
|
67
|
+
end
|
68
|
+
return
|
69
|
+
end
|
70
|
+
|
71
|
+
def read_file(path, lang)
|
72
|
+
resources_regex = /<resources(?:[^>]*)>(.*)<\/resources>/m
|
73
|
+
key_regex = /<string name="(\w+)">/
|
74
|
+
comment_regex = /<!-- (.*) -->/
|
75
|
+
value_regex = /<string name="\w+">(.*)<\/string>/
|
76
|
+
key = nil
|
77
|
+
value = nil
|
78
|
+
comment = nil
|
79
|
+
|
80
|
+
File.open(path, 'r:UTF-8') do |f|
|
81
|
+
content_match = resources_regex.match(f.read)
|
82
|
+
if content_match
|
83
|
+
for line in content_match[1].split(/\r?\n/)
|
84
|
+
key_match = key_regex.match(line)
|
85
|
+
if key_match
|
86
|
+
key = key_match[1]
|
87
|
+
value_match = value_regex.match(line)
|
88
|
+
if value_match
|
89
|
+
value = value_match[1]
|
90
|
+
value = CGI.unescapeHTML(value)
|
91
|
+
value.gsub!('\\\'', '\'')
|
92
|
+
value.gsub!('\\"', '"')
|
93
|
+
value = iosify_substitutions(value)
|
94
|
+
value.gsub!(/(\\u0020)*|(\\u0020)*\z/) { |spaces| ' ' * (spaces.length / 6) }
|
95
|
+
else
|
96
|
+
value = ""
|
97
|
+
end
|
98
|
+
set_translation_for_key(key, lang, value)
|
99
|
+
if comment and comment.length > 0 and !comment.start_with?("SECTION:")
|
100
|
+
set_comment_for_key(key, comment)
|
101
|
+
end
|
102
|
+
comment = nil
|
103
|
+
end
|
104
|
+
|
105
|
+
comment_match = comment_regex.match(line)
|
106
|
+
if comment_match
|
107
|
+
comment = comment_match[1]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def write_file(path, lang)
|
115
|
+
default_lang = nil
|
116
|
+
if DEFAULT_LANG_CODES.has_key?(lang)
|
117
|
+
default_lang = DEFAULT_LANG_CODES[lang]
|
118
|
+
end
|
119
|
+
File.open(path, 'w:UTF-8') do |f|
|
120
|
+
f.puts "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Tizen Strings File -->\n<!-- Generated by Twine #{Twine::VERSION} -->\n<!-- Language: #{lang} -->"
|
121
|
+
f.write '<string_table Bversion="2.0.0.201311071819" Dversion="20120315">'
|
122
|
+
@strings.sections.each do |section|
|
123
|
+
printed_section = false
|
124
|
+
section.rows.each do |row|
|
125
|
+
if row.matches_tags?(@options[:tags], @options[:untagged])
|
126
|
+
if !printed_section
|
127
|
+
f.puts ''
|
128
|
+
if section.name && section.name.length > 0
|
129
|
+
section_name = section.name.gsub('--', '—')
|
130
|
+
f.puts "\t<!-- SECTION: #{section_name} -->"
|
131
|
+
end
|
132
|
+
printed_section = true
|
133
|
+
end
|
134
|
+
|
135
|
+
key = row.key
|
136
|
+
|
137
|
+
value = row.translated_string_for_lang(lang, default_lang)
|
138
|
+
if !value && @options[:include_untranslated]
|
139
|
+
value = row.translated_string_for_lang(@strings.language_codes[0])
|
140
|
+
end
|
141
|
+
|
142
|
+
if value # if values is nil, there was no appropriate translation, so let Tizen handle the defaulting
|
143
|
+
value = String.new(value) # use a copy to prevent modifying the original
|
144
|
+
|
145
|
+
# Tizen enforces the following rules on the values
|
146
|
+
# 1) apostrophes and quotes must be escaped with a backslash
|
147
|
+
value.gsub!('\'', '\\\\\'')
|
148
|
+
value.gsub!('"', '\\\\"')
|
149
|
+
# 2) HTML escape the string
|
150
|
+
value = CGI.escapeHTML(value)
|
151
|
+
# 3) fix substitutions (e.g. %s/%@)
|
152
|
+
value = androidify_substitutions(value)
|
153
|
+
# 4) replace beginning and end spaces with \0020. Otherwise Tizen strips them.
|
154
|
+
value.gsub!(/\A *| *\z/) { |spaces| '\u0020' * spaces.length }
|
155
|
+
|
156
|
+
comment = row.comment
|
157
|
+
if comment
|
158
|
+
comment = comment.gsub('--', '—')
|
159
|
+
end
|
160
|
+
|
161
|
+
if comment && comment.length > 0
|
162
|
+
f.puts "\t<!-- #{comment} -->\n"
|
163
|
+
end
|
164
|
+
f.puts "\t<text id=\"IDS_#{key.upcase}\">#{value}</text>"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
f.puts '</string_table>'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
data/lib/twine/plugin.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'safe_yaml/load'
|
2
|
+
|
3
|
+
SafeYAML::OPTIONS[:suppress_warnings] = true
|
4
|
+
|
5
|
+
module Twine
|
6
|
+
class Plugin
|
7
|
+
attr_reader :debug, :config
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@debug = false
|
11
|
+
require_gems
|
12
|
+
end
|
13
|
+
|
14
|
+
###
|
15
|
+
# require gems from the yaml config.
|
16
|
+
#
|
17
|
+
# gems: [twine-plugin1, twine-2]
|
18
|
+
#
|
19
|
+
# also works with single gem
|
20
|
+
#
|
21
|
+
# gems: twine-plugin1
|
22
|
+
#
|
23
|
+
def require_gems
|
24
|
+
# ./twine.yml # current working directory
|
25
|
+
# ~/.twine # home directory
|
26
|
+
# /etc/twine.yml # etc
|
27
|
+
cwd_config = join_path Dir.pwd, 'twine.yml'
|
28
|
+
home_config = join_path Dir.home, '.twine'
|
29
|
+
etc_config = '/etc/twine.yml'
|
30
|
+
|
31
|
+
config_order = [cwd_config, home_config, etc_config]
|
32
|
+
|
33
|
+
puts "Config order: #{config_order}" if debug
|
34
|
+
|
35
|
+
config_order.each do |config_file|
|
36
|
+
next unless valid_file config_file
|
37
|
+
puts "Loading: #{config_file}" if debug
|
38
|
+
@config = SafeYAML.load_file config_file
|
39
|
+
puts "Config yaml: #{config}" if debug
|
40
|
+
break
|
41
|
+
end
|
42
|
+
|
43
|
+
return unless config
|
44
|
+
|
45
|
+
# wrap gems in an array. if nil then array will be empty
|
46
|
+
Kernel.Array(config['gems']).each do |gem_path|
|
47
|
+
puts "Requiring: #{gem_path}" if debug
|
48
|
+
require gem_path
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def valid_file path
|
55
|
+
File.exist?(path) && File.readable?(path) && !File.directory?(path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def join_path *paths
|
59
|
+
File.expand_path File.join *paths
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/twine/runner.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'tmpdir'
|
2
2
|
|
3
|
+
Twine::Plugin.new # Initialize plugins first in Runner.
|
4
|
+
|
3
5
|
module Twine
|
4
6
|
VALID_COMMANDS = ['generate-string-file', 'generate-all-string-files', 'consume-string-file', 'consume-all-string-files', 'generate-loc-drop', 'consume-loc-drop', 'generate-report']
|
5
7
|
|
@@ -269,7 +271,7 @@ module Twine
|
|
269
271
|
|
270
272
|
def determine_format_given_path(path)
|
271
273
|
ext = File.extname(path)
|
272
|
-
Formatters
|
274
|
+
Formatters.formatters.each do |formatter|
|
273
275
|
if formatter::EXTENSION == ext
|
274
276
|
return formatter::FORMAT_NAME
|
275
277
|
end
|
@@ -279,7 +281,7 @@ module Twine
|
|
279
281
|
end
|
280
282
|
|
281
283
|
def determine_format_given_directory(directory)
|
282
|
-
Formatters
|
284
|
+
Formatters.formatters.each do |formatter|
|
283
285
|
if formatter.can_handle_directory?(directory)
|
284
286
|
return formatter::FORMAT_NAME
|
285
287
|
end
|
@@ -289,7 +291,7 @@ module Twine
|
|
289
291
|
end
|
290
292
|
|
291
293
|
def formatter_for_format(format)
|
292
|
-
Formatters
|
294
|
+
Formatters.formatters.each do |formatter|
|
293
295
|
if formatter::FORMAT_NAME == format
|
294
296
|
return formatter.new(@strings, @options)
|
295
297
|
end
|
data/lib/twine/version.rb
CHANGED
data/test/fixtures/en-1.json
CHANGED
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!-- Android Strings File -->
|
3
|
+
<!-- Generated by Twine 0.5.0 -->
|
4
|
+
<!-- Language: en -->
|
5
|
+
<resources>
|
6
|
+
<!-- SECTION: My Strings -->
|
7
|
+
<string name="string_with_spaces">\u0020string with spaces\u0020\u0020</string>
|
8
|
+
</resources>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!-- Android Strings File -->
|
3
|
+
<!-- Generated by Twine 0.5.0 -->
|
4
|
+
<!-- Language: en -->
|
5
|
+
<resources>
|
6
|
+
<!-- SECTION: My Strings -->
|
7
|
+
<!-- String ends with space -->
|
8
|
+
<string name="key with space ">string with space\u0020</string>
|
9
|
+
</resources>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!-- Tizen Strings File -->
|
3
|
+
<!-- Generated by Twine <%= Twine::VERSION %> -->
|
4
|
+
<!-- Language: fr -->
|
5
|
+
<string_table Bversion="2.0.0.201311071819" Dversion="20120315">
|
6
|
+
<!-- SECTION: My Strings -->
|
7
|
+
<!-- This is a comment -->
|
8
|
+
<text id="IDS_KEY1">key1-french</text>
|
9
|
+
<text id="IDS_KEY2">key2-french</text>
|
10
|
+
<text id="IDS_KEY3">key3-english</text>
|
11
|
+
<text id="IDS_KEY4">key4-english</text>
|
12
|
+
</string_table>
|
data/test/twine_test.rb
CHANGED
@@ -52,6 +52,22 @@ class TwineTest < Test::Unit::TestCase
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
def test_generate_string_file_7
|
56
|
+
Dir.mktmpdir do |dir|
|
57
|
+
output_path = File.join(dir, 'en.xml')
|
58
|
+
Twine::Runner.run(%W(generate-string-file test/fixtures/strings-2.txt #{output_path} -t tag1))
|
59
|
+
assert_equal(ERB.new(File.read('test/fixtures/test-output-10.txt')).result, File.read(output_path))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_generate_string_file_8
|
64
|
+
Dir.mktmpdir do |dir|
|
65
|
+
output_path = File.join(dir, 'fr.xml')
|
66
|
+
Twine::Runner.run(%W(generate-string-file --format tizen test/fixtures/strings-1.txt #{output_path} --include-untranslated))
|
67
|
+
assert_equal(ERB.new(File.read('test/fixtures/test-output-12.txt')).result, File.read(output_path))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
55
71
|
def test_consume_string_file_1
|
56
72
|
Dir.mktmpdir do |dir|
|
57
73
|
output_path = File.join(dir, 'strings.txt')
|
@@ -92,7 +108,31 @@ class TwineTest < Test::Unit::TestCase
|
|
92
108
|
end
|
93
109
|
end
|
94
110
|
|
111
|
+
def test_consume_string_file_6
|
112
|
+
Dir.mktmpdir do |dir|
|
113
|
+
output_path = File.join(dir, 'strings.txt')
|
114
|
+
Twine::Runner.run(%W(consume-string-file test/fixtures/strings-2.txt test/fixtures/en-3.xml -o #{output_path} -l en -a))
|
115
|
+
assert_equal(File.read('test/fixtures/test-output-11.txt'), File.read(output_path))
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
95
119
|
def test_generate_report_1
|
96
120
|
Twine::Runner.run(%w(generate-report test/fixtures/strings-1.txt))
|
97
121
|
end
|
122
|
+
|
123
|
+
def test_json_line_breaks_consume
|
124
|
+
Dir.mktmpdir do |dir|
|
125
|
+
output_path = File.join(dir, 'strings.txt')
|
126
|
+
Twine::Runner.run(%W(consume-string-file test/fixtures/test-json-line-breaks/line-breaks.txt test/fixtures/test-json-line-breaks/line-breaks.json -l fr -o #{output_path}))
|
127
|
+
assert_equal(File.read('test/fixtures/test-json-line-breaks/consumed.txt'), File.read(output_path))
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_json_line_breaks_generate
|
132
|
+
Dir.mktmpdir do |dir|
|
133
|
+
output_path = File.join(dir, 'en.json')
|
134
|
+
Twine::Runner.run(%W(generate-string-file test/fixtures/test-json-line-breaks/line-breaks.txt #{output_path}))
|
135
|
+
assert_equal(File.read('test/fixtures/test-json-line-breaks/generated.json'), File.read(output_path))
|
136
|
+
end
|
137
|
+
end
|
98
138
|
end
|
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.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastian Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.9.5
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: safe_yaml
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.3
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,7 +74,9 @@ files:
|
|
60
74
|
- lib/twine/formatters/flash.rb
|
61
75
|
- lib/twine/formatters/gettext.rb
|
62
76
|
- lib/twine/formatters/jquery.rb
|
77
|
+
- lib/twine/formatters/tizen.rb
|
63
78
|
- lib/twine/formatters.rb
|
79
|
+
- lib/twine/plugin.rb
|
64
80
|
- lib/twine/runner.rb
|
65
81
|
- lib/twine/stringsfile.rb
|
66
82
|
- lib/twine/version.rb
|
@@ -70,11 +86,19 @@ files:
|
|
70
86
|
- test/fixtures/en-1.po
|
71
87
|
- test/fixtures/en-1.strings
|
72
88
|
- test/fixtures/en-2.po
|
89
|
+
- test/fixtures/en-3.xml
|
73
90
|
- test/fixtures/fr-1.xml
|
74
91
|
- test/fixtures/strings-1.txt
|
75
92
|
- test/fixtures/strings-2.txt
|
76
93
|
- test/fixtures/strings-3.txt
|
94
|
+
- test/fixtures/test-json-line-breaks/consumed.txt
|
95
|
+
- test/fixtures/test-json-line-breaks/generated.json
|
96
|
+
- test/fixtures/test-json-line-breaks/line-breaks.json
|
97
|
+
- test/fixtures/test-json-line-breaks/line-breaks.txt
|
77
98
|
- test/fixtures/test-output-1.txt
|
99
|
+
- test/fixtures/test-output-10.txt
|
100
|
+
- test/fixtures/test-output-11.txt
|
101
|
+
- test/fixtures/test-output-12.txt
|
78
102
|
- test/fixtures/test-output-2.txt
|
79
103
|
- test/fixtures/test-output-3.txt
|
80
104
|
- test/fixtures/test-output-4.txt
|
@@ -103,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
127
|
version: '0'
|
104
128
|
requirements: []
|
105
129
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.0.
|
130
|
+
rubygems_version: 2.0.14
|
107
131
|
signing_key:
|
108
132
|
specification_version: 4
|
109
133
|
summary: Manage strings and their translations for your iOS and Android projects.
|