twine 0.1.1 → 0.1.2
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.
- data/README.md +5 -5
 - data/bin/twine +6 -1
 - data/lib/twine/cli.rb +30 -40
 - data/lib/twine/formatters/abstract.rb +35 -24
 - data/lib/twine/formatters/android.rb +14 -16
 - data/lib/twine/formatters/apple.rb +11 -15
 - data/lib/twine/runner.rb +20 -18
 - data/lib/twine/stringsfile.rb +43 -11
 - data/lib/twine/version.rb +1 -1
 - data/test/fixtures/en-1.strings +10 -0
 - data/test/fixtures/fr-1.xml +9 -0
 - data/test/fixtures/strings-1.txt +16 -0
 - data/test/fixtures/test-output-1.txt +10 -0
 - data/test/fixtures/test-output-2.txt +9 -0
 - data/test/fixtures/test-output-3.txt +17 -0
 - data/test/fixtures/test-output-4.txt +20 -0
 - data/test/twine_test.rb +40 -0
 - metadata +26 -6
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -70,7 +70,7 @@ Whitepace in this file is mostly ignored. If you absolutely need to put spaces a 
     | 
|
| 
       70 
70 
     | 
    
         | 
| 
       71 
71 
     | 
    
         
             
            ## Usage
         
     | 
| 
       72 
72 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
            	Usage: twine COMMAND STRINGS_FILE [INPUT_OR_OUTPUT_PATH] [--lang LANG1,LANG2...] [-- 
     | 
| 
      
 73 
     | 
    
         
            +
            	Usage: twine COMMAND STRINGS_FILE [INPUT_OR_OUTPUT_PATH] [--lang LANG1,LANG2...] [--tags TAG1,TAG2,TAG3...] [--format FORMAT]
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
            ### Commands
         
     | 
| 
       76 
76 
     | 
    
         | 
| 
         @@ -78,15 +78,15 @@ Whitepace in this file is mostly ignored. If you absolutely need to put spaces a 
     | 
|
| 
       78 
78 
     | 
    
         | 
| 
       79 
79 
     | 
    
         
             
            This command creates an Apple or Android strings file from the master strings data file.
         
     | 
| 
       80 
80 
     | 
    
         | 
| 
       81 
     | 
    
         
            -
            	$ twine generate-string-file /path/to/strings.txt values-ja.xml -- 
     | 
| 
       82 
     | 
    
         
            -
            	$ twine generate-string-file /path/to/strings.txt Localizable.strings --lang ja -- 
     | 
| 
      
 81 
     | 
    
         
            +
            	$ twine generate-string-file /path/to/strings.txt values-ja.xml --tags common,app1
         
     | 
| 
      
 82 
     | 
    
         
            +
            	$ twine generate-string-file /path/to/strings.txt Localizable.strings --lang ja --tags mytag
         
     | 
| 
       83 
83 
     | 
    
         
             
            	$ twine generate-string-file /path/to/strings.txt all-english.strings --lang en
         
     | 
| 
       84 
84 
     | 
    
         | 
| 
       85 
85 
     | 
    
         
             
            #### `generate-all-string-files`
         
     | 
| 
       86 
86 
     | 
    
         | 
| 
       87 
87 
     | 
    
         
             
            This command is a convenient way to call `generate-string-file` multiple times. It uses standard Mac OS X, iOS, and Android conventions to figure out exactly which files to create given a parent directory. For example, if you point it to a parent directory containing `en.lproj`, `fr.lproj`, and `ja.lproj` subdirectories, Twine will create a `Localizable.strings` file of the appropriate language in each of them. This is often the command you will want to execute during the build phase of your project.
         
     | 
| 
       88 
88 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
            	$ twine generate-all-string-files /path/to/strings.txt /path/to/project/locales/directory -- 
     | 
| 
      
 89 
     | 
    
         
            +
            	$ twine generate-all-string-files /path/to/strings.txt /path/to/project/locales/directory --tags common,app1
         
     | 
| 
       90 
90 
     | 
    
         | 
| 
       91 
91 
     | 
    
         
             
            #### `consume-string-file`
         
     | 
| 
       92 
92 
     | 
    
         | 
| 
         @@ -101,7 +101,7 @@ This command slurps all of the strings from a `.strings` or `.xml` file and inco 
     | 
|
| 
       101 
101 
     | 
    
         
             
            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.
         
     | 
| 
       102 
102 
     | 
    
         | 
| 
       103 
103 
     | 
    
         
             
            	$ twine generate-loc-drop /path/to/strings.txt LocDrop1.zip
         
     | 
| 
       104 
     | 
    
         
            -
            	$ twine generate-loc-drop /path/to/strings.txt LocDrop2.zip --lang en,fr,ja,ko -- 
     | 
| 
      
 104 
     | 
    
         
            +
            	$ twine generate-loc-drop /path/to/strings.txt LocDrop2.zip --lang en,fr,ja,ko --tags common,app1
         
     | 
| 
       105 
105 
     | 
    
         | 
| 
       106 
106 
     | 
    
         
             
            #### `consume-loc-drop`
         
     | 
| 
       107 
107 
     | 
    
         | 
    
        data/bin/twine
    CHANGED
    
    
    
        data/lib/twine/cli.rb
    CHANGED
    
    | 
         @@ -12,8 +12,8 @@ module Twine 
     | 
|
| 
       12 
12 
     | 
    
         
             
                end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                def parse_args
         
     | 
| 
       15 
     | 
    
         
            -
                  parser = OptionParser.new 
     | 
| 
       16 
     | 
    
         
            -
                    opts.banner = 'Usage: twine COMMAND STRINGS_FILE [INPUT_OR_OUTPUT_PATH] [--lang LANG1,LANG2...] [-- 
     | 
| 
      
 15 
     | 
    
         
            +
                  parser = OptionParser.new do |opts|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    opts.banner = 'Usage: twine COMMAND STRINGS_FILE [INPUT_OR_OUTPUT_PATH] [--lang LANG1,LANG2...] [--tags TAG1,TAG2,TAG3...] [--format FORMAT]'
         
     | 
| 
       17 
17 
     | 
    
         
             
                    opts.separator ''
         
     | 
| 
       18 
18 
     | 
    
         
             
                    opts.separator 'The purpose of this script is to convert back and forth between multiple data formats, allowing us to treat our strings (and translations) as data stored in a text file. We can then use the data file to create drops for the localization team, consume similar drops returned by the localization team, generate reports on the strings, as well as create iOS and Android string files to ship with our products.'
         
     | 
| 
       19 
19 
     | 
    
         
             
                    opts.separator ''
         
     | 
| 
         @@ -36,7 +36,7 @@ module Twine 
     | 
|
| 
       36 
36 
     | 
    
         
             
                    opts.on('-l', '--lang LANGUAGES', Array, 'The language code(s) to use for the specified action.') do |langs|
         
     | 
| 
       37 
37 
     | 
    
         
             
                      @options[:languages] = langs
         
     | 
| 
       38 
38 
     | 
    
         
             
                    end
         
     | 
| 
       39 
     | 
    
         
            -
                    opts.on('-t', '-- 
     | 
| 
      
 39 
     | 
    
         
            +
                    opts.on('-t', '--tags TAGS', Array, 'The tag(s) to use for the specified action. Only strings with that tag will be processed.') do |tags|
         
     | 
| 
       40 
40 
     | 
    
         
             
                      @options[:tags] = tags
         
     | 
| 
       41 
41 
     | 
    
         
             
                    end
         
     | 
| 
       42 
42 
     | 
    
         
             
                    opts.on('-f', '--format FORMAT', 'The file format to read or write (iOS, Android). Additional formatters can be placed in the formats/ directory.') do |format|
         
     | 
| 
         @@ -49,10 +49,16 @@ module Twine 
     | 
|
| 
       49 
49 
     | 
    
         
             
                        end
         
     | 
| 
       50 
50 
     | 
    
         
             
                      end
         
     | 
| 
       51 
51 
     | 
    
         
             
                      if !found_format
         
     | 
| 
       52 
     | 
    
         
            -
                        puts "Invalid format: #{format}"
         
     | 
| 
      
 52 
     | 
    
         
            +
                        STDERR.puts "Invalid format: #{format}"
         
     | 
| 
       53 
53 
     | 
    
         
             
                      end
         
     | 
| 
       54 
54 
     | 
    
         
             
                      @options[:format] = lformat
         
     | 
| 
       55 
55 
     | 
    
         
             
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    opts.on('-a', '--all', 'Normally, when consuming a string file, Twine will ignore any string keys that do not exist in your master file. This flag will force those missing strings to be added to your master file.') do |a|
         
     | 
| 
      
 57 
     | 
    
         
            +
                      @options[:consume_all] = true
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    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|
         
     | 
| 
      
 60 
     | 
    
         
            +
                      @options[:output_path] = o
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
       56 
62 
     | 
    
         
             
                    opts.on('-h', '--help', 'Show this message.') do |h|
         
     | 
| 
       57 
63 
     | 
    
         
             
                      puts opts.help
         
     | 
| 
       58 
64 
     | 
    
         
             
                      exit
         
     | 
| 
         @@ -64,14 +70,14 @@ module Twine 
     | 
|
| 
       64 
70 
     | 
    
         
             
                    opts.separator ''
         
     | 
| 
       65 
71 
     | 
    
         
             
                    opts.separator 'Examples:'
         
     | 
| 
       66 
72 
     | 
    
         
             
                    opts.separator ''
         
     | 
| 
       67 
     | 
    
         
            -
                    opts.separator '> twine generate-string-file strings.txt ko.xml -- 
     | 
| 
       68 
     | 
    
         
            -
                    opts.separator '> twine generate-all-string-files strings.txt Resources/Locales/ -- 
     | 
| 
      
 73 
     | 
    
         
            +
                    opts.separator '> twine generate-string-file strings.txt ko.xml --tags FT'
         
     | 
| 
      
 74 
     | 
    
         
            +
                    opts.separator '> twine generate-all-string-files strings.txt Resources/Locales/ --tags FT,FB'
         
     | 
| 
       69 
75 
     | 
    
         
             
                    opts.separator '> twine consume-string-file strings.txt ja.strings'
         
     | 
| 
       70 
     | 
    
         
            -
                    opts.separator '> twine generate-loc-drop strings.txt LocDrop5.zip -- 
     | 
| 
      
 76 
     | 
    
         
            +
                    opts.separator '> twine generate-loc-drop strings.txt LocDrop5.zip --tags FT,FB --format android --lang de,en,en-GB,ja,ko'
         
     | 
| 
       71 
77 
     | 
    
         
             
                    opts.separator '> twine consume-loc-drop strings.txt LocDrop5.zip'
         
     | 
| 
       72 
78 
     | 
    
         
             
                    opts.separator '> twine generate-report strings.txt'
         
     | 
| 
       73 
79 
     | 
    
         
             
                  end
         
     | 
| 
       74 
     | 
    
         
            -
                  parser.parse!
         
     | 
| 
      
 80 
     | 
    
         
            +
                  parser.parse! @args
         
     | 
| 
       75 
81 
     | 
    
         | 
| 
       76 
82 
     | 
    
         
             
                  if @args.length == 0
         
     | 
| 
       77 
83 
     | 
    
         
             
                    puts parser.help
         
     | 
| 
         @@ -81,13 +87,11 @@ module Twine 
     | 
|
| 
       81 
87 
     | 
    
         
             
                  @options[:command] = @args[0]
         
     | 
| 
       82 
88 
     | 
    
         | 
| 
       83 
89 
     | 
    
         
             
                  if !VALID_COMMANDS.include? @options[:command]
         
     | 
| 
       84 
     | 
    
         
            -
                     
     | 
| 
       85 
     | 
    
         
            -
                    exit
         
     | 
| 
      
 90 
     | 
    
         
            +
                    raise Twine::Error.new "Invalid command: #{@options[:command]}"
         
     | 
| 
       86 
91 
     | 
    
         
             
                  end
         
     | 
| 
       87 
92 
     | 
    
         | 
| 
       88 
93 
     | 
    
         
             
                  if @args.length == 1
         
     | 
| 
       89 
     | 
    
         
            -
                     
     | 
| 
       90 
     | 
    
         
            -
                    exit
         
     | 
| 
      
 94 
     | 
    
         
            +
                    raise Twine::Error.new 'You must specify your strings file.'
         
     | 
| 
       91 
95 
     | 
    
         
             
                  end
         
     | 
| 
       92 
96 
     | 
    
         | 
| 
       93 
97 
     | 
    
         
             
                  @options[:strings_file] = @args[1]
         
     | 
| 
         @@ -97,68 +101,54 @@ module Twine 
     | 
|
| 
       97 
101 
     | 
    
         
             
                    if @args.length == 3
         
     | 
| 
       98 
102 
     | 
    
         
             
                      @options[:output_path] = @args[2]
         
     | 
| 
       99 
103 
     | 
    
         
             
                    elsif @args.length > 3
         
     | 
| 
       100 
     | 
    
         
            -
                       
     | 
| 
       101 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 104 
     | 
    
         
            +
                      raise Twine::Error.new "Unknown argument: #{@args[3]}"
         
     | 
| 
       102 
105 
     | 
    
         
             
                    else
         
     | 
| 
       103 
     | 
    
         
            -
                       
     | 
| 
       104 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 106 
     | 
    
         
            +
                      raise Twine::Error.new 'Not enough arguments.'
         
     | 
| 
       105 
107 
     | 
    
         
             
                    end
         
     | 
| 
       106 
108 
     | 
    
         
             
                    if @options[:languages] and @options[:languages].length > 1
         
     | 
| 
       107 
     | 
    
         
            -
                       
     | 
| 
       108 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 109 
     | 
    
         
            +
                      raise Twine::Error.new 'Please only specify a single language for the generate-string-file command.'
         
     | 
| 
       109 
110 
     | 
    
         
             
                    end
         
     | 
| 
       110 
111 
     | 
    
         
             
                  when 'generate-all-string-files'
         
     | 
| 
       111 
112 
     | 
    
         
             
                    if ARGV.length == 3
         
     | 
| 
       112 
113 
     | 
    
         
             
                      @options[:output_path] = @args[2]
         
     | 
| 
       113 
114 
     | 
    
         
             
                    elsif @args.length > 3
         
     | 
| 
       114 
     | 
    
         
            -
                       
     | 
| 
       115 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 115 
     | 
    
         
            +
                      raise Twine::Error.new "Unknown argument: #{@args[3]}"
         
     | 
| 
       116 
116 
     | 
    
         
             
                    else
         
     | 
| 
       117 
     | 
    
         
            -
                       
     | 
| 
       118 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 117 
     | 
    
         
            +
                      raise Twine::Error.new 'Not enough arguments.'
         
     | 
| 
       119 
118 
     | 
    
         
             
                    end
         
     | 
| 
       120 
119 
     | 
    
         
             
                  when 'consume-string-file'
         
     | 
| 
       121 
120 
     | 
    
         
             
                    if @args.length == 3
         
     | 
| 
       122 
121 
     | 
    
         
             
                      @options[:input_path] = @args[2]
         
     | 
| 
       123 
122 
     | 
    
         
             
                    elsif @args.length > 3
         
     | 
| 
       124 
     | 
    
         
            -
                       
     | 
| 
       125 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 123 
     | 
    
         
            +
                      raise Twine::Error.new "Unknown argument: #{@args[3]}"
         
     | 
| 
       126 
124 
     | 
    
         
             
                    else
         
     | 
| 
       127 
     | 
    
         
            -
                       
     | 
| 
       128 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 125 
     | 
    
         
            +
                      raise Twine::Error.new 'Not enough arguments.'
         
     | 
| 
       129 
126 
     | 
    
         
             
                    end
         
     | 
| 
       130 
127 
     | 
    
         
             
                    if @options[:languages] and @options[:languages].length > 1
         
     | 
| 
       131 
     | 
    
         
            -
                       
     | 
| 
       132 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 128 
     | 
    
         
            +
                      raise Twine::Error.new 'Please only specify a single language for the consume-string-file command.'
         
     | 
| 
       133 
129 
     | 
    
         
             
                    end
         
     | 
| 
       134 
130 
     | 
    
         
             
                  when 'generate-loc-drop'
         
     | 
| 
       135 
131 
     | 
    
         
             
                    if @args.length == 3
         
     | 
| 
       136 
132 
     | 
    
         
             
                      @options[:output_path] = @args[2]
         
     | 
| 
       137 
133 
     | 
    
         
             
                    elsif @args.length > 3
         
     | 
| 
       138 
     | 
    
         
            -
                       
     | 
| 
       139 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 134 
     | 
    
         
            +
                      raise Twine::Error.new "Unknown argument: #{@args[3]}"
         
     | 
| 
       140 
135 
     | 
    
         
             
                    else
         
     | 
| 
       141 
     | 
    
         
            -
                       
     | 
| 
       142 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 136 
     | 
    
         
            +
                      raise Twine::Error.new 'Not enough arguments.'
         
     | 
| 
       143 
137 
     | 
    
         
             
                    end
         
     | 
| 
       144 
138 
     | 
    
         
             
                    if !@options[:format]
         
     | 
| 
       145 
     | 
    
         
            -
                       
     | 
| 
       146 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 139 
     | 
    
         
            +
                      raise Twine::Error.new 'You must specify a format.'
         
     | 
| 
       147 
140 
     | 
    
         
             
                    end
         
     | 
| 
       148 
141 
     | 
    
         
             
                  when 'consume-loc-drop'
         
     | 
| 
       149 
142 
     | 
    
         
             
                    if @args.length == 3
         
     | 
| 
       150 
143 
     | 
    
         
             
                      @options[:input_path] = @args[2]
         
     | 
| 
       151 
144 
     | 
    
         
             
                    elsif @args.length > 3
         
     | 
| 
       152 
     | 
    
         
            -
                       
     | 
| 
       153 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 145 
     | 
    
         
            +
                      raise Twine::Error.new "Unknown argument: #{@args[3]}"
         
     | 
| 
       154 
146 
     | 
    
         
             
                    else
         
     | 
| 
       155 
     | 
    
         
            -
                       
     | 
| 
       156 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 147 
     | 
    
         
            +
                      raise Twine::Error.new 'Not enough arguments.'
         
     | 
| 
       157 
148 
     | 
    
         
             
                    end
         
     | 
| 
       158 
149 
     | 
    
         
             
                  when 'generate-report'
         
     | 
| 
       159 
150 
     | 
    
         
             
                    if @args.length > 2
         
     | 
| 
       160 
     | 
    
         
            -
                       
     | 
| 
       161 
     | 
    
         
            -
                      exit
         
     | 
| 
      
 151 
     | 
    
         
            +
                      raise Twine::Error.new "Unknown argument: #{@args[2]}"
         
     | 
| 
       162 
152 
     | 
    
         
             
                    end
         
     | 
| 
       163 
153 
     | 
    
         
             
                  end
         
     | 
| 
       164 
154 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1,10 +1,41 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Twine
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Formatters
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Abstract
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_accessor :strings
         
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_accessor :options
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       4 
7 
     | 
    
         
             
                  def self.can_handle_directory?(path)
         
     | 
| 
       5 
8 
     | 
    
         
             
                    return false
         
     | 
| 
       6 
9 
     | 
    
         
             
                  end
         
     | 
| 
       7 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(strings, options)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @strings = strings
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @options = options
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def set_translation_for_key(key, lang, value)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    if @strings.strings_map.include?(key)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @strings.strings_map[key].translations[lang] = value
         
     | 
| 
      
 19 
     | 
    
         
            +
                    elsif @options[:consume_all]
         
     | 
| 
      
 20 
     | 
    
         
            +
                      STDERR.puts "Adding new string '#{key}' to strings data file."
         
     | 
| 
      
 21 
     | 
    
         
            +
                      arr = @strings.sections.select { |s| s.name == 'Uncategorized' }
         
     | 
| 
      
 22 
     | 
    
         
            +
                      current_section = arr ? arr[0] : nil
         
     | 
| 
      
 23 
     | 
    
         
            +
                      if !current_section
         
     | 
| 
      
 24 
     | 
    
         
            +
                        current_section = StringsSection.new('Uncategorized')
         
     | 
| 
      
 25 
     | 
    
         
            +
                        @strings.sections.insert(0, current_section)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                      current_row = StringsRow.new(key)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      current_section.rows << current_row
         
     | 
| 
      
 29 
     | 
    
         
            +
                      @strings.strings_map[key] = current_row
         
     | 
| 
      
 30 
     | 
    
         
            +
                      @strings.strings_map[key].translations[lang] = value
         
     | 
| 
      
 31 
     | 
    
         
            +
                    else
         
     | 
| 
      
 32 
     | 
    
         
            +
                      STDERR.puts "Warning: '#{key}' not found in strings data file."
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                    if !@strings.language_codes.include?(lang)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      @strings.add_language_code(lang)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       8 
39 
     | 
    
         
             
                  def default_file_name
         
     | 
| 
       9 
40 
     | 
    
         
             
                    raise NotImplementedError.new("You must implement default_file_name in your formatter class.")
         
     | 
| 
       10 
41 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -13,15 +44,15 @@ module Twine 
     | 
|
| 
       13 
44 
     | 
    
         
             
                    raise NotImplementedError.new("You must implement determine_language_given_path in your formatter class.")
         
     | 
| 
       14 
45 
     | 
    
         
             
                  end
         
     | 
| 
       15 
46 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                  def read_file(path, lang 
     | 
| 
      
 47 
     | 
    
         
            +
                  def read_file(path, lang)
         
     | 
| 
       17 
48 
     | 
    
         
             
                    raise NotImplementedError.new("You must implement read_file in your formatter class.")
         
     | 
| 
       18 
49 
     | 
    
         
             
                  end
         
     | 
| 
       19 
50 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                  def write_file(path, lang 
     | 
| 
      
 51 
     | 
    
         
            +
                  def write_file(path, lang)
         
     | 
| 
       21 
52 
     | 
    
         
             
                    raise NotImplementedError.new("You must implement write_file in your formatter class.")
         
     | 
| 
       22 
53 
     | 
    
         
             
                  end
         
     | 
| 
       23 
54 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                  def write_all_files(path 
     | 
| 
      
 55 
     | 
    
         
            +
                  def write_all_files(path)
         
     | 
| 
       25 
56 
     | 
    
         
             
                    if !File.directory?(path)
         
     | 
| 
       26 
57 
     | 
    
         
             
                      raise Twine::Error.new("Directory does not exist: #{path}")
         
     | 
| 
       27 
58 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -29,29 +60,9 @@ module Twine 
     | 
|
| 
       29 
60 
     | 
    
         
             
                    Dir.foreach(path) do |item|
         
     | 
| 
       30 
61 
     | 
    
         
             
                      lang = determine_language_given_path(item)
         
     | 
| 
       31 
62 
     | 
    
         
             
                      if lang
         
     | 
| 
       32 
     | 
    
         
            -
                        write_file(File.join(path, item, default_file_name), lang 
     | 
| 
       33 
     | 
    
         
            -
                      end
         
     | 
| 
       34 
     | 
    
         
            -
                    end
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  def row_matches_tags?(row, tags)
         
     | 
| 
       38 
     | 
    
         
            -
                    if tags == nil || tags.length == 0
         
     | 
| 
       39 
     | 
    
         
            -
                      return true
         
     | 
| 
       40 
     | 
    
         
            -
                    end
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                    if tags != nil && row.tags != nil
         
     | 
| 
       43 
     | 
    
         
            -
                      tags.each do |tag|
         
     | 
| 
       44 
     | 
    
         
            -
                        if row.tags.include? tag
         
     | 
| 
       45 
     | 
    
         
            -
                          return true
         
     | 
| 
       46 
     | 
    
         
            -
                        end
         
     | 
| 
      
 63 
     | 
    
         
            +
                        write_file(File.join(path, item, default_file_name), lang)
         
     | 
| 
       47 
64 
     | 
    
         
             
                      end
         
     | 
| 
       48 
65 
     | 
    
         
             
                    end
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                    return false
         
     | 
| 
       51 
     | 
    
         
            -
                  end
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                  def translated_string_for_row_and_lang(row, lang, default_lang)
         
     | 
| 
       54 
     | 
    
         
            -
                    row.translations[lang] || row.translations[default_lang]
         
     | 
| 
       55 
66 
     | 
    
         
             
                  end
         
     | 
| 
       56 
67 
     | 
    
         
             
                end
         
     | 
| 
       57 
68 
     | 
    
         
             
              end
         
     | 
| 
         @@ -21,7 +21,7 @@ module Twine 
     | 
|
| 
       21 
21 
     | 
    
         
             
                  def determine_language_given_path(path)
         
     | 
| 
       22 
22 
     | 
    
         
             
                    path_arr = path.split(File::SEPARATOR)
         
     | 
| 
       23 
23 
     | 
    
         
             
                    path_arr.each do |segment|
         
     | 
| 
       24 
     | 
    
         
            -
                      match = /^values-(.*)$/.match( 
     | 
| 
      
 24 
     | 
    
         
            +
                      match = /^values-(.*)$/.match(segment)
         
     | 
| 
       25 
25 
     | 
    
         
             
                      if match
         
     | 
| 
       26 
26 
     | 
    
         
             
                        lang = match[1]
         
     | 
| 
       27 
27 
     | 
    
         
             
                        lang.sub!('-r', '-')
         
     | 
| 
         @@ -32,33 +32,31 @@ module Twine 
     | 
|
| 
       32 
32 
     | 
    
         
             
                    return
         
     | 
| 
       33 
33 
     | 
    
         
             
                  end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                  def read_file(path, lang 
     | 
| 
      
 35 
     | 
    
         
            +
                  def read_file(path, lang)
         
     | 
| 
       36 
36 
     | 
    
         
             
                    File.open(path, 'r:UTF-8') do |f|
         
     | 
| 
      
 37 
     | 
    
         
            +
                      current_section = nil
         
     | 
| 
       37 
38 
     | 
    
         
             
                      doc = REXML::Document.new(f)
         
     | 
| 
       38 
39 
     | 
    
         
             
                      doc.elements.each('resources/string') do |ele|
         
     | 
| 
       39 
40 
     | 
    
         
             
                        key = ele.attributes["name"]
         
     | 
| 
       40 
     | 
    
         
            -
                         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                        else
         
     | 
| 
       46 
     | 
    
         
            -
                          puts "#{key} not found in strings data file."
         
     | 
| 
       47 
     | 
    
         
            -
                        end
         
     | 
| 
      
 41 
     | 
    
         
            +
                        value = ele.text || ''
         
     | 
| 
      
 42 
     | 
    
         
            +
                        value.gsub!('\\\'', '\'')
         
     | 
| 
      
 43 
     | 
    
         
            +
                        value.gsub!(/\n/, '')
         
     | 
| 
      
 44 
     | 
    
         
            +
                        value.gsub!('%s', '%@')
         
     | 
| 
      
 45 
     | 
    
         
            +
                        set_translation_for_key(key, lang, value)
         
     | 
| 
       48 
46 
     | 
    
         
             
                      end
         
     | 
| 
       49 
47 
     | 
    
         
             
                    end
         
     | 
| 
       50 
48 
     | 
    
         
             
                  end
         
     | 
| 
       51 
49 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                  def write_file(path, lang 
     | 
| 
       53 
     | 
    
         
            -
                    default_lang = strings.language_codes[0]
         
     | 
| 
      
 50 
     | 
    
         
            +
                  def write_file(path, lang)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    default_lang = @strings.language_codes[0]
         
     | 
| 
       54 
52 
     | 
    
         
             
                    File.open(path, 'w:UTF-8') do |f|
         
     | 
| 
       55 
53 
     | 
    
         
             
                      f.puts "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Android Strings File -->\n<!-- Generated by Twine -->\n<!-- Language: #{lang} -->"
         
     | 
| 
       56 
54 
     | 
    
         
             
                      f.write '<resources>'
         
     | 
| 
       57 
     | 
    
         
            -
                      strings.sections.each do |section|
         
     | 
| 
      
 55 
     | 
    
         
            +
                      @strings.sections.each do |section|
         
     | 
| 
       58 
56 
     | 
    
         
             
                        printed_section = false
         
     | 
| 
       59 
57 
     | 
    
         
             
                        section.rows.each do |row|
         
     | 
| 
       60 
     | 
    
         
            -
                          if  
     | 
| 
       61 
     | 
    
         
            -
                             
     | 
| 
      
 58 
     | 
    
         
            +
                          if row.matches_tags?(options[:tags])
         
     | 
| 
      
 59 
     | 
    
         
            +
                            if !printed_section
         
     | 
| 
       62 
60 
     | 
    
         
             
                              f.puts ''
         
     | 
| 
       63 
61 
     | 
    
         
             
                              if section.name && section.name.length > 0
         
     | 
| 
       64 
62 
     | 
    
         
             
                                section_name = section.name.gsub('--', '—')
         
     | 
| 
         @@ -70,7 +68,7 @@ module Twine 
     | 
|
| 
       70 
68 
     | 
    
         
             
                            key = row.key
         
     | 
| 
       71 
69 
     | 
    
         
             
                            key = CGI.escapeHTML(key)
         
     | 
| 
       72 
70 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
                            value =  
     | 
| 
      
 71 
     | 
    
         
            +
                            value = row.translated_string_for_lang(lang, default_lang)
         
     | 
| 
       74 
72 
     | 
    
         
             
                            value.gsub!('\'', '\\\\\'')
         
     | 
| 
       75 
73 
     | 
    
         
             
                            value.gsub!('%@', '%s')
         
     | 
| 
       76 
74 
     | 
    
         
             
                            value = CGI.escapeHTML(value)
         
     | 
| 
         @@ -25,34 +25,30 @@ module Twine 
     | 
|
| 
       25 
25 
     | 
    
         
             
                    return
         
     | 
| 
       26 
26 
     | 
    
         
             
                  end
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                  def read_file(path, lang 
     | 
| 
      
 28 
     | 
    
         
            +
                  def read_file(path, lang)
         
     | 
| 
       29 
29 
     | 
    
         
             
                    File.open(path, 'r:UTF-8') do |f|
         
     | 
| 
       30 
30 
     | 
    
         
             
                      while line = f.gets
         
     | 
| 
       31 
     | 
    
         
            -
                        match = /"((?:[^"\\]|\\.)+)"\s*=\s*"((?:[^"\\]|\\.)*)/.match(line)
         
     | 
| 
      
 31 
     | 
    
         
            +
                        match = /"((?:[^"\\]|\\.)+)"\s*=\s*"((?:[^"\\]|\\.)*)"/.match(line)
         
     | 
| 
       32 
32 
     | 
    
         
             
                        if match
         
     | 
| 
       33 
33 
     | 
    
         
             
                          key = match[1]
         
     | 
| 
       34 
34 
     | 
    
         
             
                          key.gsub!('\\"', '"')
         
     | 
| 
       35 
     | 
    
         
            -
                           
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                            strings.strings_map[key].translations[lang] = value
         
     | 
| 
       39 
     | 
    
         
            -
                          else
         
     | 
| 
       40 
     | 
    
         
            -
                            puts "#{key} not found in strings data file."
         
     | 
| 
       41 
     | 
    
         
            -
                          end
         
     | 
| 
      
 35 
     | 
    
         
            +
                          value = match[2]
         
     | 
| 
      
 36 
     | 
    
         
            +
                          value.gsub!('\\"', '"')
         
     | 
| 
      
 37 
     | 
    
         
            +
                          set_translation_for_key(key, lang, value)
         
     | 
| 
       42 
38 
     | 
    
         
             
                        end
         
     | 
| 
       43 
39 
     | 
    
         
             
                      end
         
     | 
| 
       44 
40 
     | 
    
         
             
                    end
         
     | 
| 
       45 
41 
     | 
    
         
             
                  end
         
     | 
| 
       46 
42 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
                  def write_file(path, lang 
     | 
| 
       48 
     | 
    
         
            -
                    default_lang = strings.language_codes[0]
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def write_file(path, lang)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    default_lang = @strings.language_codes[0]
         
     | 
| 
       49 
45 
     | 
    
         
             
                    File.open(path, 'w:UTF-8') do |f|
         
     | 
| 
       50 
46 
     | 
    
         
             
                      f.puts "/**\n * iOS Strings File\n * Generated by Twine\n * Language: #{lang}\n */"
         
     | 
| 
       51 
     | 
    
         
            -
                      strings.sections.each do |section|
         
     | 
| 
      
 47 
     | 
    
         
            +
                      @strings.sections.each do |section|
         
     | 
| 
       52 
48 
     | 
    
         
             
                        printed_section = false
         
     | 
| 
       53 
49 
     | 
    
         
             
                        section.rows.each do |row|
         
     | 
| 
       54 
     | 
    
         
            -
                          if  
     | 
| 
       55 
     | 
    
         
            -
                             
     | 
| 
      
 50 
     | 
    
         
            +
                          if row.matches_tags?(options[:tags])
         
     | 
| 
      
 51 
     | 
    
         
            +
                            if !printed_section
         
     | 
| 
       56 
52 
     | 
    
         
             
                              f.puts ''
         
     | 
| 
       57 
53 
     | 
    
         
             
                              if section.name && section.name.length > 0
         
     | 
| 
       58 
54 
     | 
    
         
             
                                f.puts "/* #{section.name} */"
         
     | 
| 
         @@ -63,7 +59,7 @@ module Twine 
     | 
|
| 
       63 
59 
     | 
    
         
             
                            key = row.key
         
     | 
| 
       64 
60 
     | 
    
         
             
                            key = key.gsub('"', '\\\\"')
         
     | 
| 
       65 
61 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                            value =  
     | 
| 
      
 62 
     | 
    
         
            +
                            value = row.translated_string_for_lang(lang, default_lang)
         
     | 
| 
       67 
63 
     | 
    
         
             
                            value = value.gsub('"', '\\\\"')
         
     | 
| 
       68 
64 
     | 
    
         | 
| 
       69 
65 
     | 
    
         
             
                            comment = row.comment
         
     | 
    
        data/lib/twine/runner.rb
    CHANGED
    
    | 
         @@ -16,13 +16,8 @@ module Twine 
     | 
|
| 
       16 
16 
     | 
    
         
             
                def run
         
     | 
| 
       17 
17 
     | 
    
         
             
                  # Parse all CLI arguments.
         
     | 
| 
       18 
18 
     | 
    
         
             
                  CLI::parse_args(@args, @options)
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                   
     | 
| 
       21 
     | 
    
         
            -
                    read_strings_data
         
     | 
| 
       22 
     | 
    
         
            -
                    execute_command
         
     | 
| 
       23 
     | 
    
         
            -
                  rescue Twine::Error => e
         
     | 
| 
       24 
     | 
    
         
            -
                    puts e.message
         
     | 
| 
       25 
     | 
    
         
            -
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  read_strings_data
         
     | 
| 
      
 20 
     | 
    
         
            +
                  execute_command
         
     | 
| 
       26 
21 
     | 
    
         
             
                end
         
     | 
| 
       27 
22 
     | 
    
         | 
| 
       28 
23 
     | 
    
         
             
                def read_strings_data
         
     | 
| 
         @@ -53,7 +48,7 @@ module Twine 
     | 
|
| 
       53 
48 
     | 
    
         
             
                    lang = @options[:languages][0]
         
     | 
| 
       54 
49 
     | 
    
         
             
                  end
         
     | 
| 
       55 
50 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                  read_write_string_file(@options[:output_path], false, lang 
     | 
| 
      
 51 
     | 
    
         
            +
                  read_write_string_file(@options[:output_path], false, lang)
         
     | 
| 
       57 
52 
     | 
    
         
             
                end
         
     | 
| 
       58 
53 
     | 
    
         | 
| 
       59 
54 
     | 
    
         
             
                def generate_all_string_files
         
     | 
| 
         @@ -71,7 +66,7 @@ module Twine 
     | 
|
| 
       71 
66 
     | 
    
         | 
| 
       72 
67 
     | 
    
         
             
                  formatter = formatter_for_format(format)
         
     | 
| 
       73 
68 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
                  formatter.write_all_files(@options[:output_path] 
     | 
| 
      
 69 
     | 
    
         
            +
                  formatter.write_all_files(@options[:output_path])
         
     | 
| 
       75 
70 
     | 
    
         
             
                end
         
     | 
| 
       76 
71 
     | 
    
         | 
| 
       77 
72 
     | 
    
         
             
                def consume_string_file
         
     | 
| 
         @@ -80,15 +75,17 @@ module Twine 
     | 
|
| 
       80 
75 
     | 
    
         
             
                    lang = @options[:languages][0]
         
     | 
| 
       81 
76 
     | 
    
         
             
                  end
         
     | 
| 
       82 
77 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                  read_write_string_file(@options[:input_path], true, lang 
     | 
| 
       84 
     | 
    
         
            -
                  @ 
     | 
| 
      
 78 
     | 
    
         
            +
                  read_write_string_file(@options[:input_path], true, lang)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  output_path = @options[:output_path] || @options[:strings_file]
         
     | 
| 
      
 80 
     | 
    
         
            +
                  @strings.write(output_path)
         
     | 
| 
       85 
81 
     | 
    
         
             
                end
         
     | 
| 
       86 
82 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
                def read_write_string_file(path, is_read, lang 
     | 
| 
      
 83 
     | 
    
         
            +
                def read_write_string_file(path, is_read, lang)
         
     | 
| 
       88 
84 
     | 
    
         
             
                  if is_read && !File.file?(path)
         
     | 
| 
       89 
85 
     | 
    
         
             
                    raise Twine::Error.new("File does not exist: #{path}")
         
     | 
| 
       90 
86 
     | 
    
         
             
                  end
         
     | 
| 
       91 
87 
     | 
    
         | 
| 
      
 88 
     | 
    
         
            +
                  format = @options[:format]
         
     | 
| 
       92 
89 
     | 
    
         
             
                  if !format
         
     | 
| 
       93 
90 
     | 
    
         
             
                    format = determine_format_given_path(path)
         
     | 
| 
       94 
91 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -108,10 +105,14 @@ module Twine 
     | 
|
| 
       108 
105 
     | 
    
         
             
                    raise Twine::Error.new "Unable to determine language for #{path}"
         
     | 
| 
       109 
106 
     | 
    
         
             
                  end
         
     | 
| 
       110 
107 
     | 
    
         | 
| 
      
 108 
     | 
    
         
            +
                  if !@strings.language_codes.include? lang
         
     | 
| 
      
 109 
     | 
    
         
            +
                    @strings.language_codes << lang
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
       111 
112 
     | 
    
         
             
                  if is_read
         
     | 
| 
       112 
     | 
    
         
            -
                    formatter.read_file(path, lang 
     | 
| 
      
 113 
     | 
    
         
            +
                    formatter.read_file(path, lang)
         
     | 
| 
       113 
114 
     | 
    
         
             
                  else
         
     | 
| 
       114 
     | 
    
         
            -
                    formatter.write_file(path, lang 
     | 
| 
      
 115 
     | 
    
         
            +
                    formatter.write_file(path, lang)
         
     | 
| 
       115 
116 
     | 
    
         
             
                  end
         
     | 
| 
       116 
117 
     | 
    
         
             
                end
         
     | 
| 
       117 
118 
     | 
    
         | 
| 
         @@ -162,13 +163,14 @@ module Twine 
     | 
|
| 
       162 
163 
     | 
    
         
             
                          real_path = File.join(dir, entry.name)
         
     | 
| 
       163 
164 
     | 
    
         
             
                          FileUtils.mkdir_p(File.dirname(real_path))
         
     | 
| 
       164 
165 
     | 
    
         
             
                          zipfile.extract(entry.name, real_path)
         
     | 
| 
       165 
     | 
    
         
            -
                          read_write_string_file(real_path, true, nil 
     | 
| 
      
 166 
     | 
    
         
            +
                          read_write_string_file(real_path, true, nil)
         
     | 
| 
       166 
167 
     | 
    
         
             
                        end
         
     | 
| 
       167 
168 
     | 
    
         
             
                      end
         
     | 
| 
       168 
169 
     | 
    
         
             
                    end
         
     | 
| 
       169 
170 
     | 
    
         
             
                  end
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
                  @ 
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  output_path = @options[:output_path] || @options[:strings_file]
         
     | 
| 
      
 173 
     | 
    
         
            +
                  @strings.write(output_path)
         
     | 
| 
       172 
174 
     | 
    
         
             
                end
         
     | 
| 
       173 
175 
     | 
    
         | 
| 
       174 
176 
     | 
    
         
             
                def generate_report
         
     | 
| 
         @@ -255,7 +257,7 @@ module Twine 
     | 
|
| 
       255 
257 
     | 
    
         
             
                def formatter_for_format(format)
         
     | 
| 
       256 
258 
     | 
    
         
             
                  Formatters::FORMATTERS.each do |formatter|
         
     | 
| 
       257 
259 
     | 
    
         
             
                    if formatter::FORMAT_NAME == format
         
     | 
| 
       258 
     | 
    
         
            -
                      return formatter.new
         
     | 
| 
      
 260 
     | 
    
         
            +
                      return formatter.new(@strings, @options)
         
     | 
| 
       259 
261 
     | 
    
         
             
                    end
         
     | 
| 
       260 
262 
     | 
    
         
             
                  end
         
     | 
| 
       261 
263 
     | 
    
         | 
    
        data/lib/twine/stringsfile.rb
    CHANGED
    
    | 
         @@ -21,6 +21,28 @@ module Twine 
     | 
|
| 
       21 
21 
     | 
    
         
             
                  @tags = nil
         
     | 
| 
       22 
22 
     | 
    
         
             
                  @translations = {}
         
     | 
| 
       23 
23 
     | 
    
         
             
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
                
         
     | 
| 
      
 25 
     | 
    
         
            +
                def matches_tags?(tags)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  if @tags == nil || @tags.length == 0
         
     | 
| 
      
 27 
     | 
    
         
            +
                    # This row has no tags. Never match
         
     | 
| 
      
 28 
     | 
    
         
            +
                    return false
         
     | 
| 
      
 29 
     | 
    
         
            +
                  elsif tags == nil || tags.length == 0
         
     | 
| 
      
 30 
     | 
    
         
            +
                    # The user did not specify any tags. Everything passes.
         
     | 
| 
      
 31 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 32 
     | 
    
         
            +
                  else
         
     | 
| 
      
 33 
     | 
    
         
            +
                    tags.each do |tag|
         
     | 
| 
      
 34 
     | 
    
         
            +
                      if @tags.include? tag
         
     | 
| 
      
 35 
     | 
    
         
            +
                        return true
         
     | 
| 
      
 36 
     | 
    
         
            +
                      end
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  return false
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
                
         
     | 
| 
      
 43 
     | 
    
         
            +
                def translated_string_for_lang(lang, default_lang=nil)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @translations[lang] || @translations[default_lang]
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
       24 
46 
     | 
    
         
             
              end
         
     | 
| 
       25 
47 
     | 
    
         | 
| 
       26 
48 
     | 
    
         
             
              class StringsFile
         
     | 
| 
         @@ -87,7 +109,7 @@ module Twine 
     | 
|
| 
       87 
109 
     | 
    
         
             
                            current_row.tags = value.split(',')
         
     | 
| 
       88 
110 
     | 
    
         
             
                          else
         
     | 
| 
       89 
111 
     | 
    
         
             
                            if !@language_codes.include? key
         
     | 
| 
       90 
     | 
    
         
            -
                               
     | 
| 
      
 112 
     | 
    
         
            +
                              add_language_code(key)
         
     | 
| 
       91 
113 
     | 
    
         
             
                            end
         
     | 
| 
       92 
114 
     | 
    
         
             
                            current_row.translations[key] = value
         
     | 
| 
       93 
115 
     | 
    
         
             
                          end
         
     | 
| 
         @@ -99,12 +121,6 @@ module Twine 
     | 
|
| 
       99 
121 
     | 
    
         
             
                        raise Twine::Error.new("Unable to parse line #{line_num} of #{path}: #{line}")
         
     | 
| 
       100 
122 
     | 
    
         
             
                      end
         
     | 
| 
       101 
123 
     | 
    
         
             
                    end
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
                    # Developer Language
         
     | 
| 
       104 
     | 
    
         
            -
                    dev_lang = @language_codes[0]
         
     | 
| 
       105 
     | 
    
         
            -
                    @language_codes.delete(dev_lang)
         
     | 
| 
       106 
     | 
    
         
            -
                    @language_codes.sort!
         
     | 
| 
       107 
     | 
    
         
            -
                    @language_codes.insert(0, dev_lang)
         
     | 
| 
       108 
124 
     | 
    
         
             
                  end
         
     | 
| 
       109 
125 
     | 
    
         
             
                end
         
     | 
| 
       110 
126 
     | 
    
         | 
| 
         @@ -120,13 +136,17 @@ module Twine 
     | 
|
| 
       120 
136 
     | 
    
         
             
                      f.puts "[[#{section.name}]]"
         
     | 
| 
       121 
137 
     | 
    
         | 
| 
       122 
138 
     | 
    
         
             
                      section.rows.each do |row|
         
     | 
| 
      
 139 
     | 
    
         
            +
                        f.puts "\t[#{row.key}]"
         
     | 
| 
       123 
140 
     | 
    
         
             
                        value = row.translations[dev_lang]
         
     | 
| 
       124 
     | 
    
         
            -
                        if value 
     | 
| 
       125 
     | 
    
         
            -
                           
     | 
| 
      
 141 
     | 
    
         
            +
                        if !value
         
     | 
| 
      
 142 
     | 
    
         
            +
                          puts "Warning: #{row.key} does not exist in developer language '#{dev_lang}'"
         
     | 
| 
      
 143 
     | 
    
         
            +
                        else
         
     | 
| 
      
 144 
     | 
    
         
            +
                          if value[0,1] == ' ' || value[-1,1] == ' ' || (value[0,1] == '`' && value[-1,1] == '`')
         
     | 
| 
      
 145 
     | 
    
         
            +
                            value = '`' + value + '`'
         
     | 
| 
      
 146 
     | 
    
         
            +
                          end
         
     | 
| 
      
 147 
     | 
    
         
            +
                          f.puts "\t\t#{dev_lang} = #{value}"
         
     | 
| 
       126 
148 
     | 
    
         
             
                        end
         
     | 
| 
       127 
149 
     | 
    
         | 
| 
       128 
     | 
    
         
            -
                        f.puts "\t[#{row.key}]"
         
     | 
| 
       129 
     | 
    
         
            -
                        f.puts "\t\t#{dev_lang} = #{value}"
         
     | 
| 
       130 
150 
     | 
    
         
             
                        if row.tags && row.tags.length > 0
         
     | 
| 
       131 
151 
     | 
    
         
             
                          tag_str = row.tags.join(',')
         
     | 
| 
       132 
152 
     | 
    
         
             
                          f.puts "\t\ttags = #{tag_str}"
         
     | 
| 
         @@ -147,5 +167,17 @@ module Twine 
     | 
|
| 
       147 
167 
     | 
    
         
             
                    end
         
     | 
| 
       148 
168 
     | 
    
         
             
                  end
         
     | 
| 
       149 
169 
     | 
    
         
             
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                def add_language_code(code)
         
     | 
| 
      
 172 
     | 
    
         
            +
                  if @language_codes.length == 0
         
     | 
| 
      
 173 
     | 
    
         
            +
                    @language_codes << code
         
     | 
| 
      
 174 
     | 
    
         
            +
                  elsif !@language_codes.include?(code)
         
     | 
| 
      
 175 
     | 
    
         
            +
                    dev_lang = @language_codes[0]
         
     | 
| 
      
 176 
     | 
    
         
            +
                    @language_codes << code
         
     | 
| 
      
 177 
     | 
    
         
            +
                    @language_codes.delete(dev_lang)
         
     | 
| 
      
 178 
     | 
    
         
            +
                    @language_codes.sort!
         
     | 
| 
      
 179 
     | 
    
         
            +
                    @language_codes.insert(0, dev_lang)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  end
         
     | 
| 
      
 181 
     | 
    
         
            +
                end
         
     | 
| 
       150 
182 
     | 
    
         
             
              end
         
     | 
| 
       151 
183 
     | 
    
         
             
            end
         
     | 
    
        data/lib/twine/version.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,9 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <?xml version="1.0" encoding="utf-8"?>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <!-- Android Strings File -->
         
     | 
| 
      
 3 
     | 
    
         
            +
            <!-- Generated by Twine -->
         
     | 
| 
      
 4 
     | 
    
         
            +
            <!-- Language: fr -->
         
     | 
| 
      
 5 
     | 
    
         
            +
            <resources>
         
     | 
| 
      
 6 
     | 
    
         
            +
            	<string name="key1">key1-french</string>
         
     | 
| 
      
 7 
     | 
    
         
            +
            	<string name="key2">key2-french</string>
         
     | 
| 
      
 8 
     | 
    
         
            +
            	<string name="key3">key3-french</string>
         
     | 
| 
      
 9 
     | 
    
         
            +
            </resources>
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            [[My Strings]]
         
     | 
| 
      
 2 
     | 
    
         
            +
            	[key1]
         
     | 
| 
      
 3 
     | 
    
         
            +
            		en = key1-english
         
     | 
| 
      
 4 
     | 
    
         
            +
            		tags = tag1
         
     | 
| 
      
 5 
     | 
    
         
            +
            		es = key1-spanish
         
     | 
| 
      
 6 
     | 
    
         
            +
            		fr = key1-french
         
     | 
| 
      
 7 
     | 
    
         
            +
            	[key2]
         
     | 
| 
      
 8 
     | 
    
         
            +
            		en = key2-english
         
     | 
| 
      
 9 
     | 
    
         
            +
            		tags = tag2
         
     | 
| 
      
 10 
     | 
    
         
            +
            		fr = key2-french
         
     | 
| 
      
 11 
     | 
    
         
            +
            	[key3]
         
     | 
| 
      
 12 
     | 
    
         
            +
            		en = key3-english
         
     | 
| 
      
 13 
     | 
    
         
            +
            		tags = tag1,tag2
         
     | 
| 
      
 14 
     | 
    
         
            +
            		es = key3-spanish
         
     | 
| 
      
 15 
     | 
    
         
            +
            	[key4]
         
     | 
| 
      
 16 
     | 
    
         
            +
            		en = key4-english
         
     | 
| 
         @@ -0,0 +1,10 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <?xml version="1.0" encoding="utf-8"?>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <!-- Android Strings File -->
         
     | 
| 
      
 3 
     | 
    
         
            +
            <!-- Generated by Twine -->
         
     | 
| 
      
 4 
     | 
    
         
            +
            <!-- Language: fr -->
         
     | 
| 
      
 5 
     | 
    
         
            +
            <resources>
         
     | 
| 
      
 6 
     | 
    
         
            +
            	<!-- My Strings -->
         
     | 
| 
      
 7 
     | 
    
         
            +
            	<string name="key1">key1-french</string>
         
     | 
| 
      
 8 
     | 
    
         
            +
            	<string name="key2">key2-french</string>
         
     | 
| 
      
 9 
     | 
    
         
            +
            	<string name="key3">key3-english</string>
         
     | 
| 
      
 10 
     | 
    
         
            +
            </resources>
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            [[My Strings]]
         
     | 
| 
      
 2 
     | 
    
         
            +
            	[key1]
         
     | 
| 
      
 3 
     | 
    
         
            +
            		en = key1-english
         
     | 
| 
      
 4 
     | 
    
         
            +
            		tags = tag1
         
     | 
| 
      
 5 
     | 
    
         
            +
            		es = key1-spanish
         
     | 
| 
      
 6 
     | 
    
         
            +
            		fr = key1-french
         
     | 
| 
      
 7 
     | 
    
         
            +
            	[key2]
         
     | 
| 
      
 8 
     | 
    
         
            +
            		en = key2-english
         
     | 
| 
      
 9 
     | 
    
         
            +
            		tags = tag2
         
     | 
| 
      
 10 
     | 
    
         
            +
            		fr = key2-french
         
     | 
| 
      
 11 
     | 
    
         
            +
            	[key3]
         
     | 
| 
      
 12 
     | 
    
         
            +
            		en = key3-english
         
     | 
| 
      
 13 
     | 
    
         
            +
            		tags = tag1,tag2
         
     | 
| 
      
 14 
     | 
    
         
            +
            		es = key3-spanish
         
     | 
| 
      
 15 
     | 
    
         
            +
            		fr = key3-french
         
     | 
| 
      
 16 
     | 
    
         
            +
            	[key4]
         
     | 
| 
      
 17 
     | 
    
         
            +
            		en = key4-english
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            [[Uncategorized]]
         
     | 
| 
      
 2 
     | 
    
         
            +
            	[key5]
         
     | 
| 
      
 3 
     | 
    
         
            +
            		en = A new string
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            [[My Strings]]
         
     | 
| 
      
 6 
     | 
    
         
            +
            	[key1]
         
     | 
| 
      
 7 
     | 
    
         
            +
            		en = key1-english
         
     | 
| 
      
 8 
     | 
    
         
            +
            		tags = tag1
         
     | 
| 
      
 9 
     | 
    
         
            +
            		es = key1-spanish
         
     | 
| 
      
 10 
     | 
    
         
            +
            		fr = key1-french
         
     | 
| 
      
 11 
     | 
    
         
            +
            	[key2]
         
     | 
| 
      
 12 
     | 
    
         
            +
            		en = key2-english
         
     | 
| 
      
 13 
     | 
    
         
            +
            		tags = tag2
         
     | 
| 
      
 14 
     | 
    
         
            +
            		fr = key2-french
         
     | 
| 
      
 15 
     | 
    
         
            +
            	[key3]
         
     | 
| 
      
 16 
     | 
    
         
            +
            		en = key3-english
         
     | 
| 
      
 17 
     | 
    
         
            +
            		tags = tag1,tag2
         
     | 
| 
      
 18 
     | 
    
         
            +
            		es = key3-spanish
         
     | 
| 
      
 19 
     | 
    
         
            +
            	[key4]
         
     | 
| 
      
 20 
     | 
    
         
            +
            		en = key4-english
         
     | 
    
        data/test/twine_test.rb
    ADDED
    
    | 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'twine'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class TwineTest < Test::Unit::TestCase
         
     | 
| 
      
 5 
     | 
    
         
            +
              def test_generate_string_file_1
         
     | 
| 
      
 6 
     | 
    
         
            +
                Dir.mktmpdir do |dir|
         
     | 
| 
      
 7 
     | 
    
         
            +
                  output_path = File.join(dir, 'fr.xml')
         
     | 
| 
      
 8 
     | 
    
         
            +
                  Twine::Runner.run(%W(generate-string-file test/fixtures/strings-1.txt #{output_path}))
         
     | 
| 
      
 9 
     | 
    
         
            +
                  assert_equal(File.read('test/fixtures/test-output-1.txt'), File.read(output_path))
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              def test_generate_string_file_2
         
     | 
| 
      
 14 
     | 
    
         
            +
                Dir.mktmpdir do |dir|
         
     | 
| 
      
 15 
     | 
    
         
            +
                  output_path = File.join(dir, 'en.strings')
         
     | 
| 
      
 16 
     | 
    
         
            +
                  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 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def test_consume_string_file_1
         
     | 
| 
      
 22 
     | 
    
         
            +
                Dir.mktmpdir do |dir|
         
     | 
| 
      
 23 
     | 
    
         
            +
                  output_path = File.join(dir, 'strings.txt')
         
     | 
| 
      
 24 
     | 
    
         
            +
                  Twine::Runner.run(%W(consume-string-file test/fixtures/strings-1.txt test/fixtures/fr-1.xml -o #{output_path} -l fr))
         
     | 
| 
      
 25 
     | 
    
         
            +
                  assert_equal(File.read('test/fixtures/test-output-3.txt'), File.read(output_path))
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              def test_consume_string_file_2
         
     | 
| 
      
 30 
     | 
    
         
            +
                Dir.mktmpdir do |dir|
         
     | 
| 
      
 31 
     | 
    
         
            +
                  output_path = File.join(dir, 'strings.txt')
         
     | 
| 
      
 32 
     | 
    
         
            +
                  Twine::Runner.run(%W(consume-string-file test/fixtures/strings-1.txt test/fixtures/en-1.strings -o #{output_path} -l en -a))
         
     | 
| 
      
 33 
     | 
    
         
            +
                  assert_equal(File.read('test/fixtures/test-output-4.txt'), File.read(output_path))
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
              
         
     | 
| 
      
 37 
     | 
    
         
            +
              def test_generate_report_1
         
     | 
| 
      
 38 
     | 
    
         
            +
                Twine::Runner.run(%w(generate-report test/fixtures/strings-1.txt))
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 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.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.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-02- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2012-02-11 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: rubyzip
         
     | 
| 
       16 
     | 
    
         
            -
              requirement: & 
     | 
| 
      
 16 
     | 
    
         
            +
              requirement: &70180596581660 !ruby/object:Gem::Requirement
         
     | 
| 
       17 
17 
     | 
    
         
             
                none: false
         
     | 
| 
       18 
18 
     | 
    
         
             
                requirements:
         
     | 
| 
       19 
19 
     | 
    
         
             
                - - ~>
         
     | 
| 
         @@ -21,7 +21,18 @@ dependencies: 
     | 
|
| 
       21 
21 
     | 
    
         
             
                    version: 0.9.5
         
     | 
| 
       22 
22 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       23 
23 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       24 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 24 
     | 
    
         
            +
              version_requirements: *70180596581660
         
     | 
| 
      
 25 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 26 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 27 
     | 
    
         
            +
              requirement: &70180596581180 !ruby/object:Gem::Requirement
         
     | 
| 
      
 28 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 29 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 30 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: 0.9.2
         
     | 
| 
      
 33 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 34 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 35 
     | 
    
         
            +
              version_requirements: *70180596581180
         
     | 
| 
       25 
36 
     | 
    
         
             
            description: ! "  Twine is a command line tool for managing your strings and their
         
     | 
| 
       26 
37 
     | 
    
         
             
              translations.\n  \n  It is geared toward Mac OS X, iOS, and Android developers.\n"
         
     | 
| 
       27 
38 
     | 
    
         
             
            email: twine@mobiata.com
         
     | 
| 
         @@ -43,6 +54,14 @@ files: 
     | 
|
| 
       43 
54 
     | 
    
         
             
            - lib/twine/version.rb
         
     | 
| 
       44 
55 
     | 
    
         
             
            - lib/twine.rb
         
     | 
| 
       45 
56 
     | 
    
         
             
            - bin/twine
         
     | 
| 
      
 57 
     | 
    
         
            +
            - test/fixtures/en-1.strings
         
     | 
| 
      
 58 
     | 
    
         
            +
            - test/fixtures/fr-1.xml
         
     | 
| 
      
 59 
     | 
    
         
            +
            - test/fixtures/strings-1.txt
         
     | 
| 
      
 60 
     | 
    
         
            +
            - test/fixtures/test-output-1.txt
         
     | 
| 
      
 61 
     | 
    
         
            +
            - test/fixtures/test-output-2.txt
         
     | 
| 
      
 62 
     | 
    
         
            +
            - test/fixtures/test-output-3.txt
         
     | 
| 
      
 63 
     | 
    
         
            +
            - test/fixtures/test-output-4.txt
         
     | 
| 
      
 64 
     | 
    
         
            +
            - test/twine_test.rb
         
     | 
| 
       46 
65 
     | 
    
         
             
            homepage: https://github.com/mobiata/twine
         
     | 
| 
       47 
66 
     | 
    
         
             
            licenses: []
         
     | 
| 
       48 
67 
     | 
    
         
             
            post_install_message: 
         
     | 
| 
         @@ -54,7 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       54 
73 
     | 
    
         
             
              requirements:
         
     | 
| 
       55 
74 
     | 
    
         
             
              - - ! '>='
         
     | 
| 
       56 
75 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       57 
     | 
    
         
            -
                  version:  
     | 
| 
      
 76 
     | 
    
         
            +
                  version: 1.8.7
         
     | 
| 
       58 
77 
     | 
    
         
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
       59 
78 
     | 
    
         
             
              none: false
         
     | 
| 
       60 
79 
     | 
    
         
             
              requirements:
         
     | 
| 
         @@ -67,4 +86,5 @@ rubygems_version: 1.8.11 
     | 
|
| 
       67 
86 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       68 
87 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       69 
88 
     | 
    
         
             
            summary: Manage strings and their translations for your iOS and Android projects.
         
     | 
| 
       70 
     | 
    
         
            -
            test_files: 
     | 
| 
      
 89 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 90 
     | 
    
         
            +
            - test/twine_test.rb
         
     |