ricotta 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ricotta (0.0.1)
5
+ commander (~> 4.1.2)
6
+ faraday (~> 0.8.0)
7
+ faraday_middleware (~> 0.9.0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ commander (4.1.3)
13
+ highline (~> 1.6.11)
14
+ faraday (0.8.7)
15
+ multipart-post (~> 1.1)
16
+ faraday_middleware (0.9.0)
17
+ faraday (>= 0.7.4, < 0.9)
18
+ highline (1.6.19)
19
+ multipart-post (1.2.0)
20
+ rake (0.9.6)
21
+ rspec (0.6.4)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ rake (~> 0.9.2)
28
+ ricotta!
29
+ rspec (~> 0.6.1)
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Erik Sundin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ Ricotta is a web based translation management tool, with complimentary build
2
+ tools, to efficiently manage localized resources in your software project.
3
+
4
+ - http://ricotta-open.appspot.com
5
+ - https://github.com/sosandstrom/ricotta
6
+
7
+ ## About
8
+
9
+ The ricotta gem integrates with the Ricotta translation tool to make it easier
10
+ to keep translations up to date in your software projects, all from the command line.
11
+
12
+ ## Installation
13
+
14
+ gem install ricotta
15
+
16
+ ## Usage
17
+
18
+ $ ricotta
19
+
20
+ Download translations from Ricotta
21
+
22
+ Commands:
23
+ dump Dump translations from Ricotta into local files.
24
+ help Display global or [command] help documentation.
25
+ install:xcode Fetch translations from Ricotta and install them into an Xcode project
26
+
27
+ Global Options:
28
+ -h, --help Display help documentation
29
+ -v, --version Display version information
30
+ -t, --trace Display backtrace when an error occurs
31
+
32
+ ### Install into an Xcode project
33
+
34
+ $ cd projects/MyXcodeProject
35
+ $ ricotta install:xcode -u http://ricotta-open.appspot.com \
36
+ -p MyRicottaProject \
37
+ -l en
38
+
39
+ Or by recommendation, create a `.ricottarc` file (see below) and execute.
40
+
41
+ $ ricotta install:xcode
42
+
43
+ ## Configuration
44
+
45
+ You can configure ricotta by using a ricotta configuration file.
46
+ The recommended name is `.ricottarc` but a custom file can be passed by using the `-c` option.
47
+
48
+ # My Ricotta configuration
49
+ url: http://ricotta-open.appspot.com
50
+ project: MyProject
51
+ language: en,es,pt
52
+ branch: staging
53
+ template: my_translation_template
54
+
55
+ Ricotta automatically searches for `.ricottarc` in the current working directory and in the users home directory.
56
+ Multiple configurations are automatically merged.
57
+
58
+ Multiple configurations example:
59
+
60
+ # Global config in ~/.ricottarc
61
+ url: http://ricotta.mycompany.com
62
+ subset: ios
63
+
64
+ App configurations
65
+
66
+ # /Users/es/dev/projects/MyiOSApp
67
+ project: MyApp
68
+ language: en,es
69
+ name_token: appName
70
+
71
+ And
72
+
73
+ # /Users/es/dev/projects/MyOtheriOSApp
74
+ project: MyOtherApp
75
+ language: en,pt,ru
76
+ name_token: applicationName
77
+ subset: iphone #override global config
78
+
79
+ ## Contact
80
+
81
+ Erik Sundin
82
+
83
+ - erik@eriksundin.se
84
+
85
+ ## License
86
+
87
+ Ricotta gem is available under the MIT license. See the LICENSE file for more info.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler"
2
+ Bundler.setup
3
+
4
+ gemspec = eval(File.read("ricotta.gemspec"))
5
+
6
+ task :build => "#{gemspec.full_name}.gem"
7
+
8
+ file "#{gemspec.full_name}.gem" => gemspec.files + ["ricotta.gemspec"] do
9
+ system "gem build ricotta.gemspec"
10
+ end
data/bin/ricotta ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'commander/import'
4
+
5
+ $:.push File.expand_path("../../lib", __FILE__)
6
+ require 'ricotta'
7
+
8
+ HighLine.track_eof = false # Fix for built-in Ruby
9
+
10
+ program :version, Ricotta::VERSION
11
+ program :description, 'Download translations from Ricotta'
12
+
13
+ program :help, 'Author', 'Erik Sundin <erik@eriksundin.se>'
14
+ program :help, 'Website', 'http://github.com/eriksundin'
15
+ program :help_formatter, :compact
16
+
17
+ default_command :help
18
+
19
+ require 'ricotta/commands'
data/lib/ricotta.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Ricotta
2
+ VERSION = '0.0.1'
3
+ end
4
+
5
+ require 'ricotta/fetcher'
6
+ require 'ricotta/configuration'
@@ -0,0 +1,4 @@
1
+ $:.push File.expand_path('../', __FILE__)
2
+
3
+ require 'commands/dump'
4
+ require 'commands/xcode'
@@ -0,0 +1,69 @@
1
+ require 'yaml'
2
+
3
+ command :'dump' do |c|
4
+ c.syntax = "ricotta dump [options]"
5
+ c.summary = "Dump translations from Ricotta into local files."
6
+ c.description = "Fetched translations will written to one file per language"
7
+ c.option '-u', '--url URL', "Ricotta application URL"
8
+ c.option '-p', '--project PROJECT', "The Ricotta project"
9
+ c.option '-l', '--language LANGUAGE', "Comma separated list of language codes"
10
+ c.option '-T', '--template TEMPLATE', "Template name"
11
+ c.option '--subset SUBSET', "The subset name"
12
+ c.option '--branch BRANCH', "The branch name ('trunk' if not set)"
13
+ c.option '--config FILE', "Load default options from a configuration file"
14
+
15
+ c.action do |args, options|
16
+ options.default :branch => 'trunk'
17
+
18
+ global_config = Ricotta::Configuration::Config.new(options.config)
19
+ options.url = global_config[:url] unless options.url
20
+ options.project = global_config[:project] unless options.project
21
+ options.language = global_config[:language] unless options.language
22
+ options.subset = global_config[:subset] unless options.subset
23
+ options.template = global_config[:template] unless options.template
24
+ options.branch = global_config[:branch] if global_config[:branch] and options.branch.eql?('trunk')
25
+
26
+
27
+ determine_url! unless @url = options.url
28
+ determine_project! unless @project = options.project
29
+ determine_language! unless @language = options.language
30
+ determine_template! unless @template = options.template
31
+
32
+ languages = @language.split(',')
33
+
34
+ client = Ricotta::Fetcher::Client.new(@url)
35
+
36
+ languages.each do |language|
37
+
38
+ response = client.fetch(@project, options.branch, language, @template, options.subset)
39
+ case response.status
40
+ when 200
41
+ output = "#{@project}.#{language}"
42
+ File.open(output, 'w') { |file| file.write("#{response.body}") }
43
+ say_ok "#{language} translations downloaded to #{output}"
44
+ else
45
+ say_error "Failed to download translations for #{language}: #{response.status} #{response.body}\n"
46
+ abort
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def determine_url!
54
+ @url ||= ask "Ricotta URL:"
55
+ end
56
+
57
+ def determine_project!
58
+ @project ||= ask "Project:"
59
+ end
60
+
61
+ def determine_template!
62
+ @template ||= ask "Template:"
63
+ end
64
+
65
+ def determine_language!
66
+ @language ||= ask "Language(s):"
67
+ end
68
+
69
+ end
@@ -0,0 +1,96 @@
1
+
2
+ command :'install:xcode' do |c|
3
+ c.syntax = "ricotta install:xcode [options]"
4
+ c.summary = "Fetch translations from Ricotta and install them into an Xcode project"
5
+ c.description = "Execute this command in the root of the Xcode project."
6
+ c.option '-u', '--url URL', "Ricotta application URL"
7
+ c.option '-p', '--project PROJECT', "The Ricotta project"
8
+ c.option '-l', '--language LANGUAGE', "Comma separated list of language codes"
9
+ c.option '--subset SUBSET', "Subset name"
10
+ c.option '--name_token NAMETOKEN', "A token within the translations to install as the localized CFBundleDisplayName"
11
+ c.option '--lproj_dir LPROJDIR', "Home dir of the localized Xcode project folders (default: scans the working directory)"
12
+ c.option '--template TEMPLATE', "The template (default: 'localizable_strings_padding')"
13
+ c.option '--branch BRANCH', "The branch name (default: 'trunk')"
14
+ c.option '--config FILE', "Load default options from a configuration file"
15
+
16
+ c.action do |args, options|
17
+ options.default :branch => 'trunk', :template => 'localizable_strings_padding'
18
+
19
+ global_config = Ricotta::Configuration::Config.new(options.config)
20
+ options.url = global_config[:url] unless options.url
21
+ options.project = global_config[:project] unless options.project
22
+ options.language = global_config[:language] unless options.language
23
+ options.subset = global_config[:subset] unless options.subset
24
+ options.template = global_config[:template] if global_config[:template] and options.template.eql?('localizable_strings_padding')
25
+ options.branch = global_config[:branch] if global_config[:branch] and options.branch.eql?('trunk')
26
+
27
+ options.name_token = global_config[:name_token] unless options.name_token
28
+ options.lproj_dir = global_config[:lproj_dir] unless options.lproj_dir
29
+
30
+ determine_url! unless @url = options.url
31
+ determine_project! unless @project = options.project
32
+ determine_language! unless @language = options.language
33
+
34
+ unless @resource_path = options.lproj_dir
35
+ resource_dir_lookup = Dir.glob('**/*.lproj').first
36
+ @resource_path = File.dirname(resource_dir_lookup) if resource_dir_lookup
37
+ end
38
+
39
+ determine_resource_path! unless @resource_path
40
+ @resource_path = File.expand_path(@resource_path)
41
+ say_error "The directory #{@resource_path} does not exist" and abort unless File.directory?(@resource_path)
42
+
43
+ languages = @language.split(',')
44
+ client = Ricotta::Fetcher::Client.new(@url)
45
+
46
+ languages.each do |language|
47
+ say_ok "processing #{language}"
48
+ response = client.fetch(@project, options.branch, language, options.template, options.subset)
49
+ case response.status
50
+ when 200
51
+ lproj_base_dir = "#{@resource_path}/#{language}.lproj"
52
+ Dir.mkdir(lproj_base_dir) unless File.directory?(lproj_base_dir)
53
+ strings_file = "#{lproj_base_dir}/Localizable.strings"
54
+ File.open(strings_file, 'w') { |file| file.write("#{response.body}") }
55
+ say_ok "created #{strings_file}"
56
+
57
+ if options.name_token
58
+ File.open(strings_file).each do |line|
59
+ if line.start_with?(options.name_token)
60
+ app_name = line.split('=').last.strip.split('"')[1]
61
+ say_error "The token #{options.name_token} is missing or empty for language #{language}" and abort unless app_name.length > 0
62
+
63
+ info_plist_strings = "#{lproj_base_dir}/InfoPlist.strings"
64
+ File.open(info_plist_strings, 'w') { |file| file.write("CFBundleDisplayName=\"#{app_name}\";\n") }
65
+ say_ok "created #{info_plist_strings} with CFBundleDisplayName '#{app_name}'"
66
+
67
+ break
68
+ end
69
+ end
70
+ end
71
+ else
72
+ say_error "Failed to download translations for #{language}: #{response.status} #{response.body}\n" and abort
73
+ end
74
+ end
75
+ say_ok "translations for #{@project} installed"
76
+ end
77
+
78
+ private
79
+
80
+ def determine_resource_path!
81
+ @resource_path ||= ask "Destination for .lproj folders:"
82
+ end
83
+
84
+ def determine_url!
85
+ @url ||= ask "Ricotta URL:"
86
+ end
87
+
88
+ def determine_project!
89
+ @project ||= ask "Project:"
90
+ end
91
+
92
+ def determine_language!
93
+ @language ||= ask "Language(s):"
94
+ end
95
+
96
+ end
@@ -0,0 +1,26 @@
1
+ require 'yaml'
2
+
3
+ module Ricotta::Configuration
4
+ class Config
5
+
6
+ def initialize(rcfile)
7
+ @config = Hash.new
8
+ parse(File.expand_path('~/.ricottarc'))
9
+ parse('.ricottarc')
10
+ parse(rcfile)
11
+ end
12
+
13
+ def [](key)
14
+ return @config["#{key}"]
15
+ end
16
+
17
+ private
18
+
19
+ def parse(file)
20
+ if file and File.exist?(file)
21
+ YAML.load_file(file).each {|key, value| @config[key] = value }
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ module Ricotta::Fetcher
5
+ class Client
6
+
7
+ def initialize(url)
8
+ @connection = Faraday.new(:url => url) do |builder|
9
+ builder.use FaradayMiddleware::FollowRedirects
10
+ builder.adapter :net_http
11
+ end
12
+ end
13
+ def fetch(project, branch, language, template, subset)
14
+ path = "/proj/#{project}/branch/#{branch}/lang/#{language}/templ/#{template}/"
15
+ path.concat("subset/#{subset}/") if subset
16
+
17
+ @connection.get(path).on_complete do |env|
18
+ yield env[:status], env[:body] if block_given?
19
+ end
20
+ end
21
+ end
22
+ end
23
+
data/ricotta.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ricotta"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ricotta"
7
+ s.authors = ["Erik Sundin"]
8
+ s.email = "erik@eriksundin.se"
9
+ s.homepage = "http://github.com/eriksundin/ricotta-gem"
10
+ s.version = Ricotta::VERSION
11
+ s.platform = Gem::Platform::RUBY
12
+ s.summary = "Ricotta"
13
+ s.description = "Tool for downloading translations from Ricotta"
14
+
15
+ s.add_development_dependency "rspec", "~> 0.6.1"
16
+ s.add_development_dependency "rake", "~> 0.9.2"
17
+
18
+ s.add_dependency "commander", "~> 4.1.2"
19
+ s.add_dependency "faraday", "~> 0.8.0"
20
+ s.add_dependency "faraday_middleware", "~> 0.9.0"
21
+
22
+ s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ricotta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Erik Sundin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.6.1
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.6.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.9.2
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.9.2
46
+ - !ruby/object:Gem::Dependency
47
+ name: commander
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 4.1.2
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 4.1.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: faraday
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.8.0
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.8.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: faraday_middleware
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.9.0
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.9.0
94
+ description: Tool for downloading translations from Ricotta
95
+ email: erik@eriksundin.se
96
+ executables:
97
+ - ricotta
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - ./Gemfile
102
+ - ./Gemfile.lock
103
+ - ./lib/ricotta/commands/dump.rb
104
+ - ./lib/ricotta/commands/xcode.rb
105
+ - ./lib/ricotta/commands.rb
106
+ - ./lib/ricotta/configuration.rb
107
+ - ./lib/ricotta/fetcher.rb
108
+ - ./lib/ricotta.rb
109
+ - ./LICENSE
110
+ - ./Rakefile
111
+ - ./README.md
112
+ - ./ricotta.gemspec
113
+ - bin/ricotta
114
+ homepage: http://github.com/eriksundin/ricotta-gem
115
+ licenses: []
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 1.8.25
135
+ signing_key:
136
+ specification_version: 3
137
+ summary: Ricotta
138
+ test_files: []