fame 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +133 -0
- data/bin/fame +79 -0
- data/lib/fame.rb +5 -0
- data/lib/fame/interface_builder.rb +139 -0
- data/lib/fame/models.rb +30 -0
- data/lib/fame/version.rb +3 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aaa07dd2ecd76f2cf02be0a769acc8fe9f982a3d
|
4
|
+
data.tar.gz: d7a888bfbd6a93c52037b6088249b8c116abbab1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 48b11deac64f15a42d05ee456f2e167fc04d352228b6d63e992cfb6c4ac6ad64c34d665826f1a9b09a0db309d94533a7b3140bb7834ddcb0a594ec8e56ffd8ef
|
7
|
+
data.tar.gz: 45064b46d5fb314057bde5b2f0e2452b3b82217ef63659736b164865757dd519c3567bd046ff036d4b14a053c6b3ab57aab3b07cf0e7a71dcffd3a8390b5820d
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Alexander Schuch
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Fame
|
2
|
+
|
3
|
+
Delightful localization of .storyboard and .xib files, right within Interface Builder.
|
4
|
+
|
5
|
+
Fame makes it easy to enable specific Interface Builder elements to be translated and exported to localizable .strings files.
|
6
|
+
|
7
|
+
## Introduction
|
8
|
+
|
9
|
+
Compared to localization in code (`NSLocalizedString`), Storyboard and XIB localizations are a tedious task for both developers and translators.
|
10
|
+
|
11
|
+
#### Static vs. dynamic localization
|
12
|
+
|
13
|
+
Storyboard and XIB files usually contain a mixed set of elements with *static* or *dynamic* text:
|
14
|
+
* **Static text**: Elements with fixed localization strings that will never change at runtime
|
15
|
+
* **Dynamic text**: Elements that will change their localized text during runtime. For example a label that is populated with data from an API or a status label that is populated using `NSLocalizedString` at runtime.
|
16
|
+
|
17
|
+
**Static text elements should be localized using a generated .strings file, dynamic text elements should be ignored during translation.**
|
18
|
+
|
19
|
+
However, Storyboard and XIB .stings files generated by Xcode also contain dynamic text localizations that will always be overridden at runtime. This makes it hard to distinguish between localizations that should be translated and dynamic text that can be safely ignored during translation.
|
20
|
+
Its up to the app developers to either manually remove generated localizations that should not be translated, or leave them for the translators to waste their time with.
|
21
|
+
|
22
|
+
#### Localization comments
|
23
|
+
|
24
|
+
Storyboard and XIB .stings files generated by Xcode **do not provide a useful comment that provides context to the translator**.
|
25
|
+
|
26
|
+
```css
|
27
|
+
/* Class = "UILabel"; text = "Label"; ObjectID = "Rfi-2u-xEd"; */
|
28
|
+
"Rfi-2u-xEd.text" = "Label";
|
29
|
+
```
|
30
|
+
|
31
|
+
Translators use this comment to make sure their translation fits into the context it is used in. Its again up to the app developers to either manually search for specific translations and add a comment, or leave let the translators figure out how to find the best translation without context.
|
32
|
+
|
33
|
+
|
34
|
+
## Why Fame?
|
35
|
+
|
36
|
+
Fame solves the above mentioned issues to help developers and translators get the most out of tedious localization tasks.
|
37
|
+
|
38
|
+
#### Integrated into Interface Builder
|
39
|
+
|
40
|
+
Fame makes it easy for developers to specify which elements of your Storyboard and XIB files should be translated, all right within interface builder. Developers may also add a comment for each element to provide additional context to translators.
|
41
|
+
|
42
|
+
![Interface Builder Integration](docs/ib_detail.png)
|
43
|
+
|
44
|
+
#### Command line interface
|
45
|
+
|
46
|
+
Using the fame CLI, developers can export .strings files that only contain localizations for elements previously enabled in Interface Builder.
|
47
|
+
|
48
|
+
![gif]()
|
49
|
+
|
50
|
+
#### Generates beautiful .strings files
|
51
|
+
|
52
|
+
Translators only receive the strings that should actually be translated, saving them time (and you potentially lots of money). All generated .strings files also contain each element's name and a useful comment to provide more context by the app developer.
|
53
|
+
|
54
|
+
```css
|
55
|
+
/* MyViewController.label.text: Explains how to purchase a pro subscription. */
|
56
|
+
"Rfi-2u-xEd.text" = "Label";
|
57
|
+
```
|
58
|
+
|
59
|
+
## Installation
|
60
|
+
|
61
|
+
Install the fame ruby gem using your terminal to get access to the fame command line interface.
|
62
|
+
|
63
|
+
```bash
|
64
|
+
$ gem install fame
|
65
|
+
```
|
66
|
+
|
67
|
+
#### Enable localization for Interface Builder files
|
68
|
+
|
69
|
+
> **Note**: You may skip to the next section if you have already setup your project and Interface Builder files for localization.
|
70
|
+
|
71
|
+
First off, add all supported languages to your project. This can be done by clicking the + button under your project's Localizations configuration. Go ahead and add as many languages as you want.
|
72
|
+
|
73
|
+
![Add new language to project](docs/add_language.png)
|
74
|
+
|
75
|
+
Next, make sure to enable localization for your Interface Builder files and choose the "Localizable Strings" option from the dropdown.
|
76
|
+
|
77
|
+
![Add new language to project](docs/storyboard_setup.png)
|
78
|
+
|
79
|
+
You should now have a Base Interface Builder file (e.g. `Main.storyboard`) in a `Base.lproj` folder and multiple localizable strings files (e.g. `Main.strings`) each within a language folder (e.g. `en.lproj` and `de.lproj`).
|
80
|
+
|
81
|
+
![Add new language to project](docs/folder_structure.png)
|
82
|
+
|
83
|
+
That's it, read on to enable fame for localization.
|
84
|
+
|
85
|
+
#### Setup Fame for Interface Builder
|
86
|
+
|
87
|
+
In order to enable the Interface Builder integration to specify the elements that should be translated, add the **[Fame.swift](platform/Fame.swift)** file to your Xcode project. To test the Interface Builder integration, open any Interface Builder file in your project, select an element (e.g. a UILabel) and you should see a new section that lets you configure localization for this element in the Attributes inspector.
|
88
|
+
|
89
|
+
![Interface Builder Integration](docs/ib.png)
|
90
|
+
|
91
|
+
You can now enable localization for each element you want to have translated.
|
92
|
+
|
93
|
+
|
94
|
+
## Usage
|
95
|
+
|
96
|
+
|
97
|
+
Once all localizable elements have been configured in Interface Builder, you can export the localizable .strings file using the `fame` command line tool.
|
98
|
+
|
99
|
+
|
100
|
+
First, make sure to commit all local changes, just to be safe. Then open terminal, navigate to the root folder of your project and run
|
101
|
+
|
102
|
+
|
103
|
+
```bash
|
104
|
+
$ fame
|
105
|
+
```
|
106
|
+
|
107
|
+
In a nutshell, the fame command does the following:
|
108
|
+
|
109
|
+
* Find all .storyboard and .xib files in the current folder (recursively, you can also pass a subpath or file to the fame command)
|
110
|
+
* Lookup the localizable settings (you have set in Interface Builder) for each file
|
111
|
+
* Generate the full localizable .strings file using Apple's `ibtool`
|
112
|
+
* Filter the `ibtool` output based on your licalizable settings
|
113
|
+
* Save a new `<NameOfStoryboardOrXIB>.strings` file to the `en.lproj` folder
|
114
|
+
|
115
|
+
## Contributing
|
116
|
+
|
117
|
+
1. Fork it ( https://github.com/aschuch/fame/fork )
|
118
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
119
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
120
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
121
|
+
5. Create a new Pull Request
|
122
|
+
|
123
|
+
#### TODO
|
124
|
+
|
125
|
+
* Incremental updates of .string files (`ibtool --previous-file <OLD .storyboard> --incremental-file YY --localize-incremental`)
|
126
|
+
* Write tests with fixtures
|
127
|
+
|
128
|
+
## Contact
|
129
|
+
|
130
|
+
Feel free to get in touch.
|
131
|
+
|
132
|
+
* Website: <http://schuch.me>
|
133
|
+
* Twitter: [@schuchalexander](http://twitter.com/schuchalexander)
|
data/bin/fame
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('../../lib', __FILE__)
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'commander'
|
7
|
+
require 'colorize'
|
8
|
+
require 'fame/version'
|
9
|
+
require 'fame/interface_builder'
|
10
|
+
|
11
|
+
#
|
12
|
+
# The Fame CLI
|
13
|
+
#
|
14
|
+
class FameApplication
|
15
|
+
include Commander::Methods
|
16
|
+
|
17
|
+
def run
|
18
|
+
program :name, 'Fame'
|
19
|
+
program :version, Fame::VERSION
|
20
|
+
program :description, 'Replace identifiers within Apple Interface Builder files to use nice keys and descriptions for localization.'
|
21
|
+
default_command :localize
|
22
|
+
|
23
|
+
#
|
24
|
+
# Default localize command
|
25
|
+
#
|
26
|
+
command :localize do |c|
|
27
|
+
c.syntax = 'fame localize [options]'
|
28
|
+
c.description = 'Replaces generated identifiers of the given Interface Builder file(s) and generates .strings files.'
|
29
|
+
c.option '--path STRING', String, 'Path to an interface builder file or a folder that contains interface builder files.'
|
30
|
+
|
31
|
+
c.action do |args, options|
|
32
|
+
options.default :path => '.'
|
33
|
+
|
34
|
+
files = Fame::InterfaceBuilder.determine_ib_files!(options.path)
|
35
|
+
puts "\nFound #{files.count} files to localize.\n".light_black
|
36
|
+
|
37
|
+
# Generate localizable strings for each file
|
38
|
+
files.each_with_index do |f, index|
|
39
|
+
puts "(#{index+1}/#{files.count}) #{f}".light_blue
|
40
|
+
|
41
|
+
ib = Fame::InterfaceBuilder.new
|
42
|
+
|
43
|
+
# Generate new localizable.strings file
|
44
|
+
strings = ib.generate_localizable_strings(f)
|
45
|
+
|
46
|
+
if strings.empty?
|
47
|
+
puts "✔".green + " (no strings to localize)︎".yellow
|
48
|
+
else
|
49
|
+
FileUtils.mkdir_p(strings_folder(f))
|
50
|
+
File.write(strings_file_path(f), strings)
|
51
|
+
|
52
|
+
puts "✔︎".green + " Generated strings file at #{strings_file_path(f)}".black
|
53
|
+
end
|
54
|
+
|
55
|
+
puts "-----------------------------------------------------\n".light_black
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
run!
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def strings_folder(path)
|
66
|
+
folder = File.dirname(path)
|
67
|
+
File.join(folder, "..", "en.lproj")
|
68
|
+
end
|
69
|
+
|
70
|
+
def strings_file_path(path)
|
71
|
+
file_name = File.basename(path, File.extname(path))
|
72
|
+
file = File.join(strings_folder(path), "#{file_name}.strings")
|
73
|
+
File.expand_path(file)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
# run application
|
79
|
+
FameApplication.new.run
|
data/lib/fame.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'nokogiri' # to rewrite the storyboard
|
2
|
+
require 'plist' # to parse the localizable.plist file
|
3
|
+
require 'colorize' # colorful console output
|
4
|
+
require_relative 'models'
|
5
|
+
|
6
|
+
module Fame
|
7
|
+
|
8
|
+
class InterfaceBuilder
|
9
|
+
# Keypaths to custom runtime attributes (provided by iOS Extenstion, see Fame.swift)
|
10
|
+
LOCALIZATION_ENABLED_KEYPATH = "i18n_enabled".freeze
|
11
|
+
LOCALIZATION_COMMENT_KEYPATH = "i18n_comment".freeze
|
12
|
+
|
13
|
+
# All accepted Interface Builder file types
|
14
|
+
ACCEPTED_FILE_TYPES = [".storyboard", ".xib"].freeze
|
15
|
+
|
16
|
+
#
|
17
|
+
# Initialization
|
18
|
+
#
|
19
|
+
def self.determine_ib_files!(path = ".")
|
20
|
+
raise "The provided file or folder does not exist" unless File.exist? path
|
21
|
+
|
22
|
+
if File.directory?(path)
|
23
|
+
files = Dir.glob(path + "/**/*{#{ACCEPTED_FILE_TYPES.join(',')}}")
|
24
|
+
raise "The provided folder did not contain any interface files (#{ACCEPTED_FILE_TYPES.join(', ')})" unless files.count > 0
|
25
|
+
return files
|
26
|
+
else
|
27
|
+
raise "The provided file is not an interface file (#{ACCEPTED_FILE_TYPES.join(', ')})" unless ACCEPTED_FILE_TYPES.include? File.extname(path)
|
28
|
+
return [path]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Generates a .strings file for the Interface Builder file at the given path.
|
34
|
+
# The output only contains elements where localization has been enabled.
|
35
|
+
#
|
36
|
+
def generate_localizable_strings(file)
|
37
|
+
localizable_strings_entries(file)
|
38
|
+
.sort_by! { |e| e.node.vc_name }
|
39
|
+
.map(&:formatted_strings_file_entry)
|
40
|
+
.join("\n\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
#
|
46
|
+
# Generates ibtool output in plist format
|
47
|
+
#
|
48
|
+
def ibtool(file)
|
49
|
+
# <dict>
|
50
|
+
# <key>6lc-A3-0nG</key>
|
51
|
+
# <dict>
|
52
|
+
# <key>text</key>
|
53
|
+
# <string>Empty localization ID</string>
|
54
|
+
# </dict>
|
55
|
+
# ...
|
56
|
+
# </dict>
|
57
|
+
output = `xcrun ibtool #{file} --localizable-strings --localizable-stringarrays`
|
58
|
+
plist = Plist::parse_xml(output)
|
59
|
+
strings = plist['com.apple.ibtool.document.localizable-strings']
|
60
|
+
string_arrays = plist['com.apple.ibtool.document.localizable-stringarrays']
|
61
|
+
|
62
|
+
[strings, string_arrays]
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Returns all XML nodes with a custom localization ID
|
67
|
+
#
|
68
|
+
def nodes(file)
|
69
|
+
storyboard = File.open(file)
|
70
|
+
doc = Nokogiri::XML(storyboard)
|
71
|
+
|
72
|
+
# Grab raw nokogiri nodes that have a localization keypath
|
73
|
+
raw_nodes = doc.xpath("//userDefinedRuntimeAttribute[@keyPath='#{LOCALIZATION_ENABLED_KEYPATH}']")
|
74
|
+
|
75
|
+
# Map raw nodes info to instances of LocalizedNode
|
76
|
+
raw_nodes.map do |node|
|
77
|
+
parent = node.parent.parent # i.e. UILabel, UISwitch, etc.
|
78
|
+
vc = parent.xpath("ancestor::viewController") # the view controller of the element (only available in .storyboard files)
|
79
|
+
element_name = parent.name # i.e. label, switch
|
80
|
+
original_id = parent['id'] # ugly Xcode ID, e.g. F4z-Kg-ni6
|
81
|
+
vc_name = vc.attr('customClass').value rescue nil # name of custom view controller class
|
82
|
+
|
83
|
+
i18n_enabled = node.parent.xpath("userDefinedRuntimeAttribute[@keyPath='#{LOCALIZATION_ENABLED_KEYPATH}']").attr('value').value == "YES" rescue false
|
84
|
+
i18n_comment = node.parent.xpath("userDefinedRuntimeAttribute[@keyPath='#{LOCALIZATION_COMMENT_KEYPATH}']").attr('value').value rescue nil
|
85
|
+
|
86
|
+
LocalizedNode.new(node, original_id, vc_name, element_name, i18n_enabled, i18n_comment)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Returns the localizable strings entries for a given
|
92
|
+
# Interface Builder file.
|
93
|
+
#
|
94
|
+
def localizable_strings_entries(file)
|
95
|
+
# Generate ibtool output
|
96
|
+
strings, string_arrays = ibtool(file)
|
97
|
+
|
98
|
+
# Get nodes for current file
|
99
|
+
nodes = nodes(file)
|
100
|
+
|
101
|
+
# Generate new strings file
|
102
|
+
entries = []
|
103
|
+
nodes.each do |node|
|
104
|
+
next unless node.i18n_enabled
|
105
|
+
unless element = strings[node.original_id] || string_arrays[node.original_id]
|
106
|
+
puts " ✘ #{node.original_id} (#{node.element_name}): #{node.original_id} not found in ibtool output".red
|
107
|
+
next
|
108
|
+
end
|
109
|
+
|
110
|
+
# A localization may contain more than one element.
|
111
|
+
# e.g. a UITextField has a `text` and a `placeholdertext` localization
|
112
|
+
element.each do |property, value|
|
113
|
+
next if property == "ibExternalUserDefinedRuntimeAttributesLocalizableStrings"
|
114
|
+
|
115
|
+
if value.is_a?(Array)
|
116
|
+
# The localization contains an array of values, e.g. when localizing a UISegmentedControl
|
117
|
+
value.each_with_index do |v, index|
|
118
|
+
p = "#{property}[#{index}]"
|
119
|
+
entry = LocalizableStringsEntry.new(node, p, v)
|
120
|
+
entries << entry
|
121
|
+
|
122
|
+
puts " ✔︎ #{entry.formatted_info}".green
|
123
|
+
end
|
124
|
+
else
|
125
|
+
# The localization only contains a single value
|
126
|
+
entry = LocalizableStringsEntry.new(node, property, value)
|
127
|
+
entries << entry
|
128
|
+
|
129
|
+
puts " ✔︎ #{entry.formatted_info}".green
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
entries
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
data/lib/fame/models.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Fame
|
3
|
+
|
4
|
+
# nokogiri_node = original nokogiri node
|
5
|
+
# original_id = F4z-Kg-ni6
|
6
|
+
# vc_name = CustomViewController (optional)
|
7
|
+
# element_name = label
|
8
|
+
# i18n_enabled = true
|
9
|
+
# i18n_comment = "Best label ever invented"
|
10
|
+
LocalizedNode = Struct.new(:nokogiri_node, :original_id, :vc_name, :element_name, :i18n_enabled, :i18n_comment)
|
11
|
+
|
12
|
+
# node = LocalizedNode
|
13
|
+
# property = localizable element, e.g. text of a label
|
14
|
+
# value = localizable strings value (i.e. the translation)
|
15
|
+
LocalizableStringsEntry = Struct.new(:node, :property, :value) do
|
16
|
+
|
17
|
+
# The formatted .strings file entry
|
18
|
+
def formatted_strings_file_entry
|
19
|
+
comment = node.i18n_comment || "No comment provided by engineer."
|
20
|
+
key = "#{node.original_id}.#{property}"
|
21
|
+
["/* #{formatted_info}: #{comment} */", "\"#{key}\" = \"#{value}\";"].join("\n")
|
22
|
+
end
|
23
|
+
|
24
|
+
# The formatted info of this entry
|
25
|
+
def formatted_info
|
26
|
+
[node.vc_name, node.element_name, property].compact.join(" ")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/lib/fame/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fame
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Schuch
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: commander
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: plist
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: colorize
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.7'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.7'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.10'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.10'
|
111
|
+
description: Delightful localization of .storyboard and .xib files, right within Interface
|
112
|
+
Builder. Fame makes it easy to enable specific Interface Builder elements to be
|
113
|
+
translated and exported to localizable .strings files.
|
114
|
+
email:
|
115
|
+
- alexander@schuch.me
|
116
|
+
executables:
|
117
|
+
- fame
|
118
|
+
extensions: []
|
119
|
+
extra_rdoc_files: []
|
120
|
+
files:
|
121
|
+
- LICENSE
|
122
|
+
- README.md
|
123
|
+
- bin/fame
|
124
|
+
- lib/fame.rb
|
125
|
+
- lib/fame/interface_builder.rb
|
126
|
+
- lib/fame/models.rb
|
127
|
+
- lib/fame/version.rb
|
128
|
+
homepage: https://twitter.com/schuchalexander
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
metadata: {}
|
132
|
+
post_install_message: |-
|
133
|
+
Please add Fame.swift to your project to enable Interface Builder support.
|
134
|
+
-> https://github.com/aschuch/fame/blob/master/platform/Fame.swift
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.4.2
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: Delightful localization of .storyboard and .xib files, right within Interface
|
154
|
+
Builder.
|
155
|
+
test_files: []
|
156
|
+
has_rdoc:
|