stringer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - rbx-18mode
5
+ - rbx-19mode
6
+ - 1.8.7
data/Gemfile ADDED
@@ -0,0 +1,25 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in stringer.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ # An IRB alternative and runtime developer console
8
+ # [pry](http://pry.github.com)
9
+ gem 'pry', '~> 0.9.10'
10
+ end
11
+
12
+ group :test do
13
+ # Adding rake for Travis.
14
+ gem 'rake'
15
+
16
+ # minitest provides a complete suite of testing facilities...
17
+ # [minitest](https://github.com/seattlerb/minitest)
18
+ gem 'minitest', '~> 3.3.0'
19
+
20
+ # Adds color to your MiniTest output
21
+ gem "minitest-rg", "~> 1.0.0"
22
+
23
+ # [mocha](http://gofreerange.com/mocha/docs)
24
+ gem 'mocha', '~> 0.12.2'
25
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,7 @@
1
+ THE BEER-WARE LICENSE (Revision 42):
2
+
3
+ <pjaspers> wrote this file. As long as you retain this notice you can
4
+ do whatever you want with this stuff. If we meet some day, and you
5
+ think this stuff is worth it, you can buy me a beer in return.
6
+
7
+ Piet Jaspers
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Stringer
2
+
3
+ Stringer takes the sting out of `genstrings`, by making it not overwriting your `Localizations.strings` file each time you run `genstrings`.
4
+
5
+ It wraps `genstrings` and adds some basic merging capabilities (add and remove keys).
6
+
7
+ ## Why?
8
+
9
+ When you run `genstrings` it goes through each of your specified `.m` files, looks for `NSLocalizedString`, parses out the key and comment, adds it to a Localizable.strings file.
10
+
11
+ Downside to this utility: it completely overwrites any changes you make to the `Localizations.strings` file (or if you give it the `-a` flag, it will at least append).
12
+
13
+ That's where `stringer` comes in, makes `genstrings` suck less.
14
+
15
+ ## Installation
16
+
17
+ The easiest way to use `stringer` at the moment is to add a `Gemfile` to the root of your project and add `stringer` to it, like so:
18
+
19
+ gem 'stringer'
20
+
21
+ Then execute:
22
+
23
+ $ bundle
24
+
25
+ Now you can create a Rakefile, and add these lines:
26
+
27
+ require "stringer"
28
+
29
+ desc "Run genstrings to update the Localizable.strings files"
30
+ task :localize do
31
+ %w(en fr nl).each do |locale|
32
+ Stringer.run(locale)
33
+ end
34
+ end
35
+
36
+ Now you can update your `Localizations.strings` file by running:
37
+
38
+ rake localize
39
+
40
+ Which will output something like this:
41
+
42
+ Generating en.lproj
43
+ - Added 3 keys (die.tijd;duvels;piet...)
44
+ - Removed 1 key (dotter...)
45
+
46
+ ## The future
47
+
48
+ `0.2.0`: Add a bin, so the Rake-file shenanigans are no longer necessary.
49
+
50
+ `0.3.0`: Ditch the dependency `genstrings` and fetch strings ourselves.
51
+
52
+ ...
53
+
54
+ `1.0.0`: Installed by default on OSX TomCat
55
+
56
+ ## Contributing
57
+
58
+ Fork it! Improve it! Test it! Rewrite it! (technology)
59
+
60
+ [![Build Status](https://secure.travis-ci.org/pjaspers/stringer.png?branch=master)](http://travis-ci.org/pjaspers/stringer)
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ desc 'Run the specs'
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'lib'
8
+ t.libs << 'specs'
9
+ t.pattern = 'specs/**/*_spec.rb'
10
+ t.verbose = true
11
+ end
12
+
13
+ task :default => :test
14
+
15
+ desc "Open an pry session with Stringer loaded"
16
+ task :console do
17
+ sh "pry -I lib -r stringer.rb"
18
+ end
data/lib/stringer.rb ADDED
@@ -0,0 +1,11 @@
1
+ require "stringer/version"
2
+ require "stringer/strings_file"
3
+ require "stringer/processor"
4
+
5
+ module Stringer
6
+
7
+ def self.run(locale, options = {})
8
+ Stringer::Processor.new(locale, options).run
9
+ end
10
+
11
+ end
@@ -0,0 +1,90 @@
1
+ module Stringer
2
+ class Processor
3
+
4
+ # The Processor will be doing the genstringing part of the
5
+ # operation.
6
+ #
7
+ # Possible options:
8
+ #
9
+ # - file_folder : Folder where `genstrings` should look for
10
+ # .m files. It searches this recursively.
11
+ # - genstrings : Location of the genstrings command
12
+ # - lproj_parent : Path to folder containing the `<locale>.lproj`
13
+ #
14
+ def initialize(locale, options = {})
15
+ options = default_options.merge(options)
16
+ @locale = locale
17
+ @files_folder = options[:files_folder]
18
+ @genstrings = options[:genstrings]
19
+ @lproj_parent = options[:lproj_parent]
20
+ end
21
+
22
+ # Some sensible defaults in a hash
23
+ def default_options
24
+ {
25
+ :lproj_parent => dir_path_for_dir_with_same_name_as_parent_dir,
26
+ :files_folder => dir_path_for_dir_with_same_name_as_parent_dir,
27
+ :genstrings => "/usr/bin/genstrings"
28
+ }
29
+ end
30
+
31
+ # If standard Xcode template is used, this is the dir where most
32
+ # files will be. For a project created with name "Something"
33
+ #
34
+ # Something:
35
+ # Something:
36
+ # en.lproj/
37
+ # *.m
38
+ #
39
+ # Returns the path
40
+ def dir_path_for_dir_with_same_name_as_parent_dir
41
+ current_dir_path = File.dirname(__FILE__)
42
+ current_dir_name = File.basename(current_dir_path)
43
+ File.join(current_dir_path, current_dir_name)
44
+ end
45
+
46
+ def genstrings_command
47
+ "#{@genstrings} -q -o #{lproj_folder} #{files.join(" ")}"
48
+ end
49
+
50
+ # Returns an array of all files needed to be processed.
51
+ def files
52
+ `find #{@files_folder} -name \*.m`.split("\n")
53
+ end
54
+
55
+ def run
56
+ log("Generating #{@locale}.lproj")
57
+ original_file = StringsFile.new(strings_file_path)
58
+ if system(genstrings_command)
59
+ new_file = StringsFile.new(strings_file_path)
60
+ added_keys, removed_keys = original_file.apply(new_file)
61
+ show_changes(added_keys, "Added")
62
+ show_changes(removed_keys, "Removed")
63
+ end
64
+ original_file.write!
65
+ end
66
+
67
+ def lproj_folder
68
+ File.join(@lproj_parent, "#{@locale}.lproj")
69
+ end
70
+
71
+ def strings_file_path
72
+ "#{lproj_folder}/Localizable.strings"
73
+ end
74
+
75
+ def log(message)
76
+ puts message
77
+ end
78
+
79
+ def show_changes(keys, string)
80
+ number = keys.count
81
+ if number == 1
82
+ string = " - #{string} #{number} key"
83
+ else
84
+ string = " - #{string} #{number} keys"
85
+ end
86
+ string << " (#{keys.join(";")[0..50]}...)" unless number == 0
87
+ log string
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,70 @@
1
+ module Stringer
2
+ class StringsFile
3
+ attr_accessor :lines
4
+
5
+ def initialize(path)
6
+ check_for_file(path)
7
+ @path = path
8
+ @lines = fetch_lines_at(path)
9
+ end
10
+
11
+ def check_for_file(path)
12
+ raise "No Localisations found at #{path}" unless File.exist?(path)
13
+ end
14
+
15
+ def fetch_lines_at(path)
16
+ IO.readlines(path, mode:"rb:UTF-16LE").collect do |l|
17
+ l.encode("UTF-8").gsub("\uFEFF", "")
18
+ end
19
+ end
20
+
21
+ def comment_lines
22
+ @lines.select{|l| l =~ /^\/\*/ }
23
+ end
24
+
25
+ def translation_lines
26
+ @lines.select{|l| l =~ /^"/}
27
+ end
28
+
29
+ def comments
30
+ @comments ||= comment_lines.collect do |line|
31
+ line.gsub("/*", "").gsub("*/", "").strip
32
+ end
33
+ end
34
+
35
+ def translation_hash
36
+ return @translation_hash if @translation_hash
37
+
38
+ @translation_hash = translation_lines.inject({}) do |r,line|
39
+ r[key_from_line(line)] = value_from_line(line)
40
+ r
41
+ end
42
+ end
43
+
44
+ def key_from_line(line)
45
+ line.split("=").first.gsub("\"", "").strip
46
+ end
47
+
48
+ def value_from_line(line)
49
+ line.split("=").last.strip.gsub(";", "").gsub("\"", "")
50
+ end
51
+
52
+ def apply(other_string_file)
53
+ removed_keys = translation_hash.keys - other_string_file.translation_hash.keys
54
+ added_keys = other_string_file.translation_hash.keys - translation_hash.keys
55
+ @translation_hash = other_string_file.translation_hash.merge(translation_hash)
56
+ removed_keys.each {|k| @translation_hash.delete(k)}
57
+ [added_keys, removed_keys]
58
+ end
59
+
60
+ def write!
61
+ File.open(@path, "wb:UTF-16LE") do |file|
62
+ file.write("\uFEFF")
63
+ file.write("/* Generated */\n")
64
+ translation_hash.each do |key, value|
65
+ file.puts "\"#{key}\" = \"#{value}\";"
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module Stringer
2
+ VERSION = "0.0.1"
3
+ end
Binary file
data/specs/helper.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "minitest/autorun"
2
+ require "mocha"
3
+
4
+ begin
5
+ # [turn](http://rubygems.org/gems/turn)
6
+ require 'turn/autorun'
7
+ rescue LoadError
8
+ end
9
+
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
11
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+
13
+ require 'stringer'
14
+
15
+ def locale_file_path
16
+ File.join(File.dirname(__FILE__), "Localizable.strings")
17
+ end
@@ -0,0 +1,21 @@
1
+ require "helper"
2
+
3
+ describe Stringer::Processor do
4
+
5
+ describe "creating the genstrings command" do
6
+
7
+ it "should use sensible defaults if no options given" do
8
+ Stringer::Processor.any_instance.stubs(:dir_path_for_dir_with_same_name_as_parent_dir).returns("path")
9
+ processor = Stringer::Processor.new("nl")
10
+ processor.stubs(:files).returns(["file_a"])
11
+ processor.genstrings_command.must_equal("/usr/bin/genstrings -q -o path/nl.lproj file_a")
12
+ end
13
+
14
+ it "should use the supplied options" do
15
+ processor = Stringer::Processor.new("nl", :files_folder => "files", :lproj_parent => "lproj_parent", :genstrings => "/opt/bin/genstrings")
16
+ processor.stubs(:files).returns(["file_a"])
17
+ processor.genstrings_command.must_equal("/opt/bin/genstrings -q -o lproj_parent/nl.lproj file_a")
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ require "helper"
2
+
3
+ describe Stringer::StringsFile do
4
+
5
+ it "should have loaded the lines from the file" do
6
+ file = Stringer::StringsFile.new(locale_file_path)
7
+ file.lines.wont_be_empty
8
+ end
9
+
10
+ it "should raise if no file found" do
11
+ -> {Stringer::StringsFile.new("404")}.must_raise RuntimeError
12
+ end
13
+
14
+ describe "transforming file to strings" do
15
+ before do
16
+ lines = ["/* A comment */",
17
+ "\"a.key\" = \"Translated Key\";\n"]
18
+ Stringer::StringsFile.any_instance.expects(:fetch_lines_at).with("path").returns(lines)
19
+ Stringer::StringsFile.any_instance.stubs(:check_for_file).with("path").returns(nil)
20
+ @file = Stringer::StringsFile.new("path")
21
+ end
22
+
23
+ it "should have transformed the comments" do
24
+ @file.comments.first.must_equal("A comment")
25
+ end
26
+
27
+ it "should have extracted the keys" do
28
+ @file.translation_hash["a.key"].wont_be_nil
29
+ end
30
+
31
+ it "should have extracted the value" do
32
+ @file.translation_hash["a.key"].must_equal "Translated Key"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ require "helper"
2
+
3
+ describe Stringer do
4
+
5
+ it "should tell the processor to run :)" do
6
+ proc = mock("Stringer::Processor")
7
+ proc.expects(:run)
8
+ Stringer::Processor.expects(:new).with("en", {}).returns(proc)
9
+ Stringer.run("en")
10
+ end
11
+ end
data/stringer.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'stringer/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "stringer"
8
+ gem.version = Stringer::VERSION
9
+ gem.authors = ["pjaspers"]
10
+ gem.email = ["piet@jaspe.rs"]
11
+ gem.description = %q{Stringer: a wrapper for genstrings}
12
+ gem.summary = %q{Stringer adds merging capabilities to genstrings}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|specs|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stringer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - pjaspers
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-02 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! 'Stringer: a wrapper for genstrings'
15
+ email:
16
+ - piet@jaspe.rs
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - .travis.yml
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - lib/stringer.rb
28
+ - lib/stringer/processor.rb
29
+ - lib/stringer/strings_file.rb
30
+ - lib/stringer/version.rb
31
+ - specs/Localizable.strings
32
+ - specs/helper.rb
33
+ - specs/processor_spec.rb
34
+ - specs/string_file_spec.rb
35
+ - specs/stringer_spec.rb
36
+ - stringer.gemspec
37
+ homepage: ''
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ segments:
50
+ - 0
51
+ hash: 1114274200452902360
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ segments:
59
+ - 0
60
+ hash: 1114274200452902360
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 1.8.24
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Stringer adds merging capabilities to genstrings
67
+ test_files:
68
+ - specs/Localizable.strings
69
+ - specs/helper.rb
70
+ - specs/processor_spec.rb
71
+ - specs/string_file_spec.rb
72
+ - specs/stringer_spec.rb