twine 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +20 -7
- data/lib/twine/cli.rb +18 -1
- data/lib/twine/formatters/abstract.rb +6 -0
- data/lib/twine/formatters/android.rb +93 -7
- data/lib/twine/formatters/apple.rb +19 -8
- data/lib/twine/runner.rb +38 -6
- data/lib/twine/stringsfile.rb +9 -2
- data/lib/twine/version.rb +1 -1
- data/lib/twine.rb +1 -1
- data/test/fixtures/test-output-1.txt +1 -1
- data/test/fixtures/test-output-2.txt +5 -3
- data/test/twine_test.rb +4 -3
- metadata +17 -7
data/README.md
CHANGED
@@ -47,7 +47,7 @@ Whitepace in this file is mostly ignored. If you absolutely need to put spaces a
|
|
47
47
|
en = No
|
48
48
|
fr = Non
|
49
49
|
ja = いいえ
|
50
|
-
|
50
|
+
|
51
51
|
[[Errors]]
|
52
52
|
[path_not_found_error]
|
53
53
|
en = The file '%@' could not be found.
|
@@ -57,7 +57,7 @@ Whitepace in this file is mostly ignored. If you absolutely need to put spaces a
|
|
57
57
|
en = The network is currently unavailable.
|
58
58
|
tags = app1
|
59
59
|
comment = An error describing when the device can not connect to the internet.
|
60
|
-
|
60
|
+
|
61
61
|
[[Escaping Example]]
|
62
62
|
[list_item_separator]
|
63
63
|
en = `, `
|
@@ -96,6 +96,12 @@ This command slurps all of the strings from a `.strings` or `.xml` file and inco
|
|
96
96
|
$ twine consume-string-file /path/to/strings.txt Localizable.strings --lang ja
|
97
97
|
$ twine consume-string-file /path/to/strings.txt es.xml
|
98
98
|
|
99
|
+
#### `consume-all-string-files`
|
100
|
+
|
101
|
+
This command reads in a folder containing many `.strings` or `.xml` files. These files should be in a standard folder hierarchy so that twine knows the language of each file. When combined with the `--developer-language`, `--consume-comments`, and `--consume-all` flags, this command is a great way to create your initial strings data file from an existing iOS or Android project. Just make sure that you create a blank strings.txt file, first!
|
102
|
+
|
103
|
+
$ twine consume-all-string-files strings.txt Resources/Locales --developer-language en --consume-all --consume-comments
|
104
|
+
|
99
105
|
#### `generate-loc-drop`
|
100
106
|
|
101
107
|
This command is a convenient way to generate a zip file containing files created by the `generate-string-file` command. It is often used for creating a single zip containing a large number of strings in all languages which you can then hand off to your translation team.
|
@@ -115,23 +121,30 @@ This command gives you useful information about your strings. It will tell you h
|
|
115
121
|
|
116
122
|
$ twine generate-report /path/to/strings.txt
|
117
123
|
|
118
|
-
##
|
124
|
+
## Creating Your First strings.txt File
|
125
|
+
|
126
|
+
The easiest way to create your first strings.txt file is to run the `consume-all-string-files` command. The one caveat is to first create a blank strings.txt file to use as your starting point. Then, just point the `consume-all-string-files` command at a directory in your project containing all of your iOS, OS X, or Android strings files.
|
127
|
+
|
128
|
+
$ touch strings.txt
|
129
|
+
$ twine consume-all-string-files strings.txt Resources/Locales --developer-language en --consume-all --consume-comments
|
130
|
+
|
131
|
+
## Twine and Your Build Process
|
119
132
|
|
120
|
-
It is easy to incorporate Twine right into your iOS and
|
133
|
+
It is easy to incorporate Twine right into your iOS and OS X app build processes.
|
121
134
|
|
122
135
|
1. In your project folder, create all of the `.lproj` directories that you need. It does not really matter where they are. We tend to put them in `Resources/Locales/`.
|
123
136
|
2. Run the `generate-all-string-files` command to create all of the string files you need in these directories. For example,
|
124
137
|
|
125
|
-
|
138
|
+
$ twine generate-all-string-files strings.txt Resources/Locales/ --tags tag1,tag2
|
126
139
|
|
127
|
-
Make sure you point Twine at your strings data file, the directory that contains all of your `.lproj` directories, and
|
140
|
+
Make sure you point Twine at your strings data file, the directory that contains all of your `.lproj` directories, and the tags that describe the strings you want to use for this project.
|
128
141
|
3. Drag the `Resources/Locales/` directory to the Xcode project navigator so that Xcode knows to include all of these strings files in your build.
|
129
142
|
4. In Xcode, navigate to the "Build Phases" tab of your target.
|
130
143
|
5. Click on the "Add Build Phase" button and select "Add Run Script".
|
131
144
|
6. Drag the new "Run Script" build phase up so that it runs earlier in the build process. It doesn't really matter where, as long as it happens before the resources are copied to your bundle.
|
132
145
|
7. Edit your script to run the exact same command you ran in step (2) above.
|
133
146
|
|
134
|
-
Now, whenever you build your application, Xcode will automatically invoke Twine to make sure that your `.strings` files are
|
147
|
+
Now, whenever you build your application, Xcode will automatically invoke Twine to make sure that your `.strings` files are up-to-date.
|
135
148
|
|
136
149
|
[rubyzip]: http://rubygems.org/gems/rubyzip
|
137
150
|
[git]: http://git-scm.org/
|
data/lib/twine/cli.rb
CHANGED
@@ -19,12 +19,14 @@ module Twine
|
|
19
19
|
opts.separator ''
|
20
20
|
opts.separator 'Commands:'
|
21
21
|
opts.separator ''
|
22
|
-
opts.separator 'generate-
|
22
|
+
opts.separator 'generate-string-file -- Generates a string file in a certain LANGUAGE given a particular FORMAT. This script will attempt to guess both the language and the format given the filename and extension. For example, "ko.xml" will generate a Korean language file for Android.'
|
23
23
|
opts.separator ''
|
24
24
|
opts.separator 'generate-all-string-files -- Generates all the string files necessary for a given project. The parent directory to all of the locale-specific directories in your project should be specified as the INPUT_OR_OUTPUT_PATH. This command will most often be executed by your build script so that each build always contains the most recent strings.'
|
25
25
|
opts.separator ''
|
26
26
|
opts.separator 'consume-string-file -- Slurps all of the strings from a translated strings file into the specified STRINGS_FILE. If you have some files returned to you by your translators you can use this command to incorporate all of their changes. This script will attempt to guess both the language and the format given the filename and extension. For example, "ja.strings" will assume that the file is a Japanese iOS strings file.'
|
27
27
|
opts.separator ''
|
28
|
+
opts.separator 'consume-all-string-files -- Slurps all of the strings from a directory into the specified STRINGS_FILE. If you have some files returned to you by your translators you can use this command to incorporate all of their changes. This script will attempt to guess both the language and the format given the filename and extension. For example, "ja.strings" will assume that the file is a Japanese iOS strings file.'
|
29
|
+
opts.separator ''
|
28
30
|
opts.separator 'generate-loc-drop -- Generates a zip archive of strings files in any format. The purpose of this command is to create a very simple archive that can be handed off to a translation team. The translation team can unzip the archive, translate all of the strings in the archived files, zip everything back up, and then hand that final archive back to be consumed by the consume-loc-drop command. This command assumes that --include-untranslated has been specified on the command line.'
|
29
31
|
opts.separator ''
|
30
32
|
opts.separator 'consume-loc-drop -- Consumes an archive of translated files. This archive should be in the same format as the one created by the generate-loc-drop command.'
|
@@ -62,6 +64,12 @@ module Twine
|
|
62
64
|
opts.on('-o', '--output-file OUTPUT_FILE', 'Write the new strings database to this file instead of replacing the original file. This flag is only useful when running the consume-string-file or consume-loc-drop commands.') do |o|
|
63
65
|
@options[:output_path] = o
|
64
66
|
end
|
67
|
+
opts.on('-d', '--developer-language LANG', 'When writing the strings data file, set the specified language as the "developer language". In practice, this just means that this language will appear first in the strings data file.') do |d|
|
68
|
+
@options[:developer_language] = d
|
69
|
+
end
|
70
|
+
opts.on('-c', '--consume-comments', 'Normally, when consuming a string file, Twine will ignore all comments in the file. With this flag set, any comments encountered will be read and parsed into the strings data file. This is especially useful when creating your first strings data file from an existing project.') do |c|
|
71
|
+
@options[:consume_comments] = true
|
72
|
+
end
|
65
73
|
opts.on('-e', '--encoding ENCODING', 'Twine defaults to encoding all output files in UTF-8. This flag will tell Twine to use an alternate encoding for these files. For example, you could use this to write Apple .strings files in UTF-16. This flag currently only works with Apple .strings files and is currently only supported in Ruby 1.9.3 or greater.') do |e|
|
66
74
|
if !"".respond_to?(:encode)
|
67
75
|
raise Twine::Error.new "The --encoding flag is only supported on Ruby 1.9.3 or greater."
|
@@ -82,6 +90,7 @@ module Twine
|
|
82
90
|
opts.separator '> twine generate-string-file strings.txt ko.xml --tags FT'
|
83
91
|
opts.separator '> twine generate-all-string-files strings.txt Resources/Locales/ --tags FT,FB'
|
84
92
|
opts.separator '> twine consume-string-file strings.txt ja.strings'
|
93
|
+
opts.separator '> twine consume-all-string-files strings.txt Resources/Locales/ --developer-language en'
|
85
94
|
opts.separator '> twine generate-loc-drop strings.txt LocDrop5.zip --tags FT,FB --format android --lang de,en,en-GB,ja,ko'
|
86
95
|
opts.separator '> twine consume-loc-drop strings.txt LocDrop5.zip'
|
87
96
|
opts.separator '> twine generate-report strings.txt'
|
@@ -136,6 +145,14 @@ module Twine
|
|
136
145
|
if @options[:languages] and @options[:languages].length > 1
|
137
146
|
raise Twine::Error.new 'Please only specify a single language for the consume-string-file command.'
|
138
147
|
end
|
148
|
+
when 'consume-all-string-files'
|
149
|
+
if @args.length == 3
|
150
|
+
@options[:input_path] = @args[2]
|
151
|
+
elsif @args.length > 3
|
152
|
+
raise Twine::Error.new "Unknown argument: #{@args[3]}"
|
153
|
+
else
|
154
|
+
raise Twine::Error.new 'Not enough arguments.'
|
155
|
+
end
|
139
156
|
when 'generate-loc-drop'
|
140
157
|
@options[:include_untranslated] = true
|
141
158
|
if @args.length == 3
|
@@ -36,6 +36,12 @@ module Twine
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
def set_comment_for_key(key, comment)
|
40
|
+
if @strings.strings_map.include?(key)
|
41
|
+
@strings.strings_map[key].comment = comment
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
39
45
|
def default_file_name
|
40
46
|
raise NotImplementedError.new("You must implement default_file_name in your formatter class.")
|
41
47
|
end
|
@@ -58,9 +58,9 @@ module Twine
|
|
58
58
|
value.gsub!('\\\'', '\'')
|
59
59
|
value.gsub!('\\"', '"')
|
60
60
|
value.gsub!(/\n/, '')
|
61
|
-
value.gsub!(/%([0-9\$]*)s/, '%\1@')
|
62
61
|
value.gsub!('<', '<')
|
63
62
|
value.gsub!('&', '&')
|
63
|
+
value = iosify_substitutions(value)
|
64
64
|
set_translation_for_key(key, lang, value)
|
65
65
|
end
|
66
66
|
end
|
@@ -72,7 +72,7 @@ module Twine
|
|
72
72
|
default_lang = DEFAULT_LANG_CODES[lang]
|
73
73
|
end
|
74
74
|
File.open(path, 'w:UTF-8') do |f|
|
75
|
-
f.puts "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Android Strings File -->\n<!-- Generated by Twine -->\n<!-- Language: #{lang} -->"
|
75
|
+
f.puts "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Android Strings File -->\n<!-- Generated by Twine #{Twine::VERSION} -->\n<!-- Language: #{lang} -->"
|
76
76
|
f.write '<resources>'
|
77
77
|
@strings.sections.each do |section|
|
78
78
|
printed_section = false
|
@@ -96,7 +96,7 @@ module Twine
|
|
96
96
|
|
97
97
|
if value # if values is nil, there was no appropriate translation, so let Android handle the defaulting
|
98
98
|
value = String.new(value) # use a copy to prevent modifying the original
|
99
|
-
|
99
|
+
|
100
100
|
# Android enforces the following rules on the values
|
101
101
|
# 1) apostrophes and quotes must be escaped with a backslash
|
102
102
|
value.gsub!('\'', '\\\\\'')
|
@@ -104,14 +104,14 @@ module Twine
|
|
104
104
|
# 2) ampersand and less-than must be in XML-escaped form
|
105
105
|
value.gsub!('&', '&')
|
106
106
|
value.gsub!('<', '<')
|
107
|
-
# 3)
|
108
|
-
value
|
109
|
-
|
107
|
+
# 3) fix substitutions (e.g. %s/%@)
|
108
|
+
value = androidify_substitutions(value)
|
109
|
+
|
110
110
|
comment = row.comment
|
111
111
|
if comment
|
112
112
|
comment = comment.gsub('--', '—')
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
if comment && comment.length > 0
|
116
116
|
f.puts "\t<!-- #{comment} -->\n"
|
117
117
|
end
|
@@ -124,6 +124,92 @@ module Twine
|
|
124
124
|
f.puts '</resources>'
|
125
125
|
end
|
126
126
|
end
|
127
|
+
|
128
|
+
def iosify_substitutions(str)
|
129
|
+
# 1) use "@" instead of "s" for substituting strings
|
130
|
+
str.gsub!(/%([0-9\$]*)s/, '%\1@')
|
131
|
+
|
132
|
+
# 2) if substitutions are numbered, see if we can remove the numbering safely
|
133
|
+
expectedSub = 1
|
134
|
+
startFound = false
|
135
|
+
foundSub = 0
|
136
|
+
str.each_char do |c|
|
137
|
+
if startFound
|
138
|
+
if c == "%"
|
139
|
+
# this is a literal %, keep moving
|
140
|
+
startFound = false
|
141
|
+
elsif c.match(/\d/)
|
142
|
+
foundSub *= 10
|
143
|
+
foundSub += Integer(c)
|
144
|
+
elsif c == "$"
|
145
|
+
if expectedSub == foundSub
|
146
|
+
# okay to keep going
|
147
|
+
startFound = false
|
148
|
+
expectedSub += 1
|
149
|
+
else
|
150
|
+
# the numbering appears to be important (or non-existent), leave it alone
|
151
|
+
return str
|
152
|
+
end
|
153
|
+
end
|
154
|
+
elsif c == "%"
|
155
|
+
startFound = true
|
156
|
+
foundSub = 0
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# if we got this far, then the numbering (if any) is in order left-to-right and safe to remove
|
161
|
+
if expectedSub > 1
|
162
|
+
str.gsub!(/%\d+\$(.)/, '%\1')
|
163
|
+
end
|
164
|
+
|
165
|
+
return str
|
166
|
+
end
|
167
|
+
|
168
|
+
def androidify_substitutions(str)
|
169
|
+
# 1) use "s" instead of "@" for substituting strings
|
170
|
+
str.gsub!(/%([0-9\$]*)@/, '%\1s')
|
171
|
+
|
172
|
+
# 2) if there is more than one substitution in a string, make sure they are numbered
|
173
|
+
substituteCount = 0
|
174
|
+
startFound = false
|
175
|
+
str.each_char do |c|
|
176
|
+
if startFound
|
177
|
+
if c == "%"
|
178
|
+
# ignore as this is a literal %
|
179
|
+
elsif c.match(/\d/)
|
180
|
+
# leave the string alone if it already has numbered substitutions
|
181
|
+
return str
|
182
|
+
else
|
183
|
+
substituteCount += 1
|
184
|
+
end
|
185
|
+
startFound = false
|
186
|
+
elsif c == "%"
|
187
|
+
startFound = true
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
if substituteCount > 1
|
192
|
+
currentSub = 1
|
193
|
+
startFound = false
|
194
|
+
newstr = ""
|
195
|
+
str.each_char do |c|
|
196
|
+
if startFound
|
197
|
+
if !(c == "%")
|
198
|
+
newstr = newstr + "#{currentSub}$"
|
199
|
+
currentSub += 1
|
200
|
+
end
|
201
|
+
startFound = false
|
202
|
+
elsif c == "%"
|
203
|
+
startFound = true
|
204
|
+
end
|
205
|
+
newstr = newstr + c
|
206
|
+
end
|
207
|
+
return newstr
|
208
|
+
else
|
209
|
+
return str
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
127
213
|
end
|
128
214
|
end
|
129
215
|
end
|
@@ -46,6 +46,7 @@ module Twine
|
|
46
46
|
end
|
47
47
|
|
48
48
|
File.open(path, mode) do |f|
|
49
|
+
last_comment = nil
|
49
50
|
while line = (sep) ? f.gets(sep) : f.gets
|
50
51
|
if encoding.index('UTF-16')
|
51
52
|
if line.respond_to? :encode!
|
@@ -62,6 +63,17 @@ module Twine
|
|
62
63
|
value = match[2]
|
63
64
|
value.gsub!('\\"', '"')
|
64
65
|
set_translation_for_key(key, lang, value)
|
66
|
+
if last_comment
|
67
|
+
set_comment_for_key(key, last_comment)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
if @options[:consume_comments]
|
71
|
+
match = /\/\* (.*) \*\//.match(line)
|
72
|
+
if match
|
73
|
+
last_comment = match[1]
|
74
|
+
else
|
75
|
+
last_comment = nil
|
76
|
+
end
|
65
77
|
end
|
66
78
|
end
|
67
79
|
end
|
@@ -71,15 +83,15 @@ module Twine
|
|
71
83
|
default_lang = @strings.language_codes[0]
|
72
84
|
encoding = @options[:output_encoding] || 'UTF-8'
|
73
85
|
File.open(path, "w:#{encoding}") do |f|
|
74
|
-
f.puts "/**\n *
|
86
|
+
f.puts "/**\n * Apple Strings File\n * Generated by Twine #{Twine::VERSION}\n * Language: #{lang}\n */"
|
75
87
|
@strings.sections.each do |section|
|
76
88
|
printed_section = false
|
77
89
|
section.rows.each do |row|
|
78
90
|
if row.matches_tags?(@options[:tags], @options[:untagged])
|
91
|
+
f.puts ''
|
79
92
|
if !printed_section
|
80
|
-
f.puts ''
|
81
93
|
if section.name && section.name.length > 0
|
82
|
-
f.
|
94
|
+
f.print "/********** #{section.name} **********/\n\n"
|
83
95
|
end
|
84
96
|
printed_section = true
|
85
97
|
end
|
@@ -95,13 +107,12 @@ module Twine
|
|
95
107
|
comment = comment.gsub('*/', '* /')
|
96
108
|
end
|
97
109
|
|
98
|
-
f.print "\"#{key}\" = \"#{value}\";"
|
99
110
|
if comment && comment.length > 0
|
100
|
-
f.print "
|
101
|
-
else
|
102
|
-
f.print "\n"
|
111
|
+
f.print "/* #{comment} */\n"
|
103
112
|
end
|
104
|
-
|
113
|
+
|
114
|
+
f.print "\"#{key}\" = \"#{value}\";\n"
|
115
|
+
end
|
105
116
|
end
|
106
117
|
end
|
107
118
|
end
|
data/lib/twine/runner.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'tmpdir'
|
2
2
|
|
3
3
|
module Twine
|
4
|
-
VALID_COMMANDS = ['generate-string-file', 'generate-all-string-files', 'consume-string-file', 'generate-loc-drop', 'consume-loc-drop', 'generate-report']
|
4
|
+
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
5
|
|
6
6
|
class Runner
|
7
7
|
def initialize(args)
|
@@ -25,6 +25,13 @@ module Twine
|
|
25
25
|
@strings.read @options[:strings_file]
|
26
26
|
end
|
27
27
|
|
28
|
+
def write_strings_data(path)
|
29
|
+
if @options[:developer_language]
|
30
|
+
@strings.set_developer_language_code(@options[:developer_language])
|
31
|
+
end
|
32
|
+
@strings.write(path)
|
33
|
+
end
|
34
|
+
|
28
35
|
def execute_command
|
29
36
|
case @options[:command]
|
30
37
|
when 'generate-string-file'
|
@@ -33,6 +40,8 @@ module Twine
|
|
33
40
|
generate_all_string_files
|
34
41
|
when 'consume-string-file'
|
35
42
|
consume_string_file
|
43
|
+
when 'consume-all-string-files'
|
44
|
+
consume_all_string_files
|
36
45
|
when 'generate-loc-drop'
|
37
46
|
generate_loc_drop
|
38
47
|
when 'consume-loc-drop'
|
@@ -55,7 +64,7 @@ module Twine
|
|
55
64
|
if !File.directory?(@options[:output_path])
|
56
65
|
raise Twine::Error.new("Directory does not exist: #{@options[:output_path]}")
|
57
66
|
end
|
58
|
-
|
67
|
+
|
59
68
|
format = @options[:format]
|
60
69
|
if !format
|
61
70
|
format = determine_format_given_directory(@options[:output_path])
|
@@ -77,7 +86,26 @@ module Twine
|
|
77
86
|
|
78
87
|
read_write_string_file(@options[:input_path], true, lang)
|
79
88
|
output_path = @options[:output_path] || @options[:strings_file]
|
80
|
-
|
89
|
+
write_strings_data(output_path)
|
90
|
+
end
|
91
|
+
|
92
|
+
def consume_all_string_files
|
93
|
+
if !File.directory?(@options[:input_path])
|
94
|
+
raise Twine::Error.new("Directory does not exist: #{@options[:output_path]}")
|
95
|
+
end
|
96
|
+
|
97
|
+
Dir.glob(File.join(@options[:input_path], "**/*")) do |item|
|
98
|
+
if File.file?(item)
|
99
|
+
begin
|
100
|
+
read_write_string_file(item, true, nil)
|
101
|
+
rescue Twine::Error => e
|
102
|
+
STDERR.puts "#{e.message}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
output_path = @options[:output_path] || @options[:strings_file]
|
108
|
+
write_strings_data(output_path)
|
81
109
|
end
|
82
110
|
|
83
111
|
def read_write_string_file(path, is_read, lang)
|
@@ -159,18 +187,22 @@ module Twine
|
|
159
187
|
Dir.mktmpdir do |dir|
|
160
188
|
Zip::ZipFile.open(@options[:input_path]) do |zipfile|
|
161
189
|
zipfile.each do |entry|
|
162
|
-
if !entry.name.end_with?'/'
|
190
|
+
if !entry.name.end_with?'/' and !File.basename(entry.name).start_with?'.'
|
163
191
|
real_path = File.join(dir, entry.name)
|
164
192
|
FileUtils.mkdir_p(File.dirname(real_path))
|
165
193
|
zipfile.extract(entry.name, real_path)
|
166
|
-
|
194
|
+
begin
|
195
|
+
read_write_string_file(real_path, true, nil)
|
196
|
+
rescue Twine::Error => e
|
197
|
+
STDERR.puts "#{e.message}"
|
198
|
+
end
|
167
199
|
end
|
168
200
|
end
|
169
201
|
end
|
170
202
|
end
|
171
203
|
|
172
204
|
output_path = @options[:output_path] || @options[:strings_file]
|
173
|
-
|
205
|
+
write_strings_data(output_path)
|
174
206
|
end
|
175
207
|
|
176
208
|
def generate_report
|
data/lib/twine/stringsfile.rb
CHANGED
@@ -21,7 +21,7 @@ module Twine
|
|
21
21
|
@tags = nil
|
22
22
|
@translations = {}
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def matches_tags?(tags, include_untagged)
|
26
26
|
if tags == nil || tags.length == 0
|
27
27
|
# The user did not specify any tags. Everything passes.
|
@@ -39,7 +39,7 @@ module Twine
|
|
39
39
|
|
40
40
|
return false
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def translated_string_for_lang(lang, default_lang=nil)
|
44
44
|
if @translations[lang]
|
45
45
|
return @translations[lang]
|
@@ -190,5 +190,12 @@ module Twine
|
|
190
190
|
@language_codes.insert(0, dev_lang)
|
191
191
|
end
|
192
192
|
end
|
193
|
+
|
194
|
+
def set_developer_language_code(code)
|
195
|
+
if @language_codes.include?(code)
|
196
|
+
@language_codes.delete(code)
|
197
|
+
end
|
198
|
+
@language_codes.insert(0, code)
|
199
|
+
end
|
193
200
|
end
|
194
201
|
end
|
data/lib/twine/version.rb
CHANGED
data/lib/twine.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
/**
|
2
|
-
*
|
3
|
-
* Generated by Twine
|
2
|
+
* Apple Strings File
|
3
|
+
* Generated by Twine <%= Twine::VERSION %>
|
4
4
|
* Language: en
|
5
5
|
*/
|
6
6
|
|
7
|
-
|
7
|
+
/********** My Strings **********/
|
8
|
+
|
8
9
|
"key1" = "key1-english";
|
10
|
+
|
9
11
|
"key3" = "key3-english";
|
data/test/twine_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ERB'
|
1
2
|
require 'test/unit'
|
2
3
|
require 'twine'
|
3
4
|
|
@@ -6,7 +7,7 @@ class TwineTest < Test::Unit::TestCase
|
|
6
7
|
Dir.mktmpdir do |dir|
|
7
8
|
output_path = File.join(dir, 'fr.xml')
|
8
9
|
Twine::Runner.run(%W(generate-string-file test/fixtures/strings-1.txt #{output_path} --include-untranslated))
|
9
|
-
assert_equal(File.read('test/fixtures/test-output-1.txt'), File.read(output_path))
|
10
|
+
assert_equal(ERB.new(File.read('test/fixtures/test-output-1.txt')).result, File.read(output_path))
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -14,7 +15,7 @@ class TwineTest < Test::Unit::TestCase
|
|
14
15
|
Dir.mktmpdir do |dir|
|
15
16
|
output_path = File.join(dir, 'en.strings')
|
16
17
|
Twine::Runner.run(%W(generate-string-file test/fixtures/strings-1.txt #{output_path} -t tag1))
|
17
|
-
assert_equal(File.read('test/fixtures/test-output-2.txt'), File.read(output_path))
|
18
|
+
assert_equal(ERB.new(File.read('test/fixtures/test-output-2.txt')).result, File.read(output_path))
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -33,7 +34,7 @@ class TwineTest < Test::Unit::TestCase
|
|
33
34
|
assert_equal(File.read('test/fixtures/test-output-4.txt'), File.read(output_path))
|
34
35
|
end
|
35
36
|
end
|
36
|
-
|
37
|
+
|
37
38
|
def test_generate_report_1
|
38
39
|
Twine::Runner.run(%w(generate-report test/fixtures/strings-1.txt))
|
39
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-04-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubyzip
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: 0.9.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.9.5
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rake
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
@@ -32,7 +37,12 @@ dependencies:
|
|
32
37
|
version: 0.9.2
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.9.2
|
36
46
|
description: ! " Twine is a command line tool for managing your strings and their
|
37
47
|
translations.\n \n It is geared toward Mac OS X, iOS, and Android developers.\n"
|
38
48
|
email: twine@mobiata.com
|
@@ -83,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
93
|
version: '0'
|
84
94
|
requirements: []
|
85
95
|
rubyforge_project:
|
86
|
-
rubygems_version: 1.8.
|
96
|
+
rubygems_version: 1.8.18
|
87
97
|
signing_key:
|
88
98
|
specification_version: 3
|
89
99
|
summary: Manage strings and their translations for your iOS and Android projects.
|