fastlane-plugin-translation 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e7a31c74e6cc591cd4799f4419ca6e8691eabe5
4
+ data.tar.gz: 7f8e1bab54481514263847f31499436f1b9b3ea9
5
+ SHA512:
6
+ metadata.gz: ca0153bd137bbc975e09f7bc10b1ea56ff97325807f91f20bb6ddf84e65711457badb085d5560363ed4c1118bd97fe666494dd2e4c8d52576f932984cb5e8465
7
+ data.tar.gz: 9a97b32244d6343e2169a3128cf07194d8c3e3fc77a048e8b48f579aaef1f73a3f5fb7b96b6eb5237668c4651ef837bc556ee3b07c9e356ea4668acb268c7a91
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Jakob Jensen <jje@trifork.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # translation plugin
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-translation)
4
+
5
+ ## Getting Started
6
+
7
+ This project is a [fastlane](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-translations`, add it to your project by running:
8
+
9
+ ```bash
10
+ fastlane add_plugin translation
11
+ ```
12
+
13
+ ## About translation
14
+
15
+ Fetch application for translations from Google sheet.
16
+
17
+ **Note to author:** Add a more detailed description about this plugin here. If your plugin contains multiple actions, make sure to mention them here.
18
+
19
+ ## Example
20
+
21
+ Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
22
+
23
+ **Note to author:** Please set up a sample project to make it easy for users to explore what your plugin does. Provide everything that is necessary to try out the plugin in this project (including a sample Xcode/Android project if necessary)
24
+
25
+ ## Run tests for this plugin
26
+
27
+ To run both the tests, and code style validation, run
28
+
29
+ ```
30
+ rake
31
+ ```
32
+
33
+ To automatically fix many of the styling issues, use
34
+ ```
35
+ rubocop -a
36
+ ```
37
+
38
+ ## Issues and Feedback
39
+
40
+ For any other issues and feedback about this plugin, please submit it to this repository.
41
+
42
+ ## Troubleshooting
43
+
44
+ If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
45
+
46
+ ## Using `fastlane` Plugins
47
+
48
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
49
+
50
+ ## About `fastlane`
51
+
52
+ `fastlane` is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
@@ -0,0 +1,16 @@
1
+ require 'fastlane/plugin/translation/version'
2
+
3
+ module Fastlane
4
+ module Translation
5
+ # Return all .rb files inside the "actions" and "helper" directory
6
+ def self.all_classes
7
+ Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
8
+ end
9
+ end
10
+ end
11
+
12
+ # By default we want to import all available actions and helpers
13
+ # A plugin can contain any number of actions and plugins
14
+ Fastlane::Translation.all_classes.each do |current|
15
+ require current
16
+ end
@@ -0,0 +1,74 @@
1
+ module Fastlane
2
+ module Actions
3
+ class CreateTranslationAction < Action
4
+ require 'google_drive'
5
+
6
+ def self.run(params)
7
+ UI.message "Logging into google using #{params[:config_path]}"
8
+ session = GoogleDrive::Session.from_config(params[:config_path])
9
+
10
+ UI.message "Creating document with title '#{params[:doc_name]}'"
11
+
12
+ file = session.spreadsheet_by_title(params[:doc_name])
13
+ if file
14
+ raise "Document already exists, please change to a different doc_name".red
15
+ else
16
+ tmp_file = "#{FastlaneCore::FastlaneFolder.path}/translations"
17
+ f = File.open(tmp_file, "w")
18
+ f.close
19
+ file = session.upload_from_file(File.absolute_path(tmp_file).to_s, params[:doc_name], convert: true, content_type: "text/csv")
20
+
21
+ File.delete(tmp_file)
22
+
23
+ file.acl.push({ type: 'user', value: params[:owner_email], role: 'owner' })
24
+ file.acl.push({ type: 'user', value: params[:seed_email], role: 'writer' }) unless params[:owner_email] == params[:seed_email]
25
+ UI.message "Done creating document, use doc_id:'#{file.id}' for pulling translations.".yellow
26
+ end
27
+ end
28
+
29
+ #####################################################
30
+ # @!group Documentation
31
+ #####################################################
32
+
33
+ def self.description
34
+ "Create sheet for translations in Google sheets."
35
+ end
36
+
37
+ def self.authors
38
+ ["Krzysztof Piatkowski", "Jakob Jensen"]
39
+ end
40
+
41
+ def self.return_value
42
+ end
43
+
44
+ def self.details
45
+ nil
46
+ end
47
+
48
+ def self.available_options
49
+ [
50
+ FastlaneCore::ConfigItem.new(key: :config_path,
51
+ env_name: "FL_TRANSLATION_CONFIG_PATH",
52
+ description: "reference for the config json file, see https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md for more info",
53
+ optional: false),
54
+ FastlaneCore::ConfigItem.new(key: :doc_name,
55
+ env_name: "FL_TRANSLATION_DOC_NAME",
56
+ description: "unique name of the google sheet",
57
+ optional: false),
58
+ FastlaneCore::ConfigItem.new(key: :owner_email,
59
+ env_name: "FL_TRANSLATION_OWNER_EMAIL",
60
+ description: "The mail to give ownership over the the document",
61
+ optional: false),
62
+ FastlaneCore::ConfigItem.new(key: :seed_email,
63
+ env_name: "FL_TRANSLATION_SEED_EMAIL",
64
+ description: "The mail to give rights when initializing the document",
65
+ optional: false)
66
+ ]
67
+ end
68
+
69
+ def self.is_supported?(platform)
70
+ true
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,182 @@
1
+ module Fastlane
2
+ module Actions
3
+ class TranslationAction < Action
4
+ require 'google_drive'
5
+ require 'csv'
6
+
7
+ def self.run(params)
8
+ UI.message "Logging into google using #{params[:config_path]}"
9
+ session = GoogleDrive::Session.from_config(params[:config_path])
10
+
11
+ UI.message "Downloading CVS to #{params[:cvs_output_path]}"
12
+ file = session.file_by_id(params[:doc_id])
13
+ file.export_as_file(params[:cvs_output_path], "text/csv")
14
+
15
+ if params[:ios_output_paths]
16
+ self.convert_csv_to_ios_paths(params[:key], params[:cvs_output_path], params[:ios_output_paths])
17
+ end
18
+
19
+ if params[:android_output_paths]
20
+ convert_csv_to_android_paths(params[:key], params[:cvs_output_path], params[:android_output_paths])
21
+ end
22
+
23
+ if params[:swift_struct_path]
24
+ self.create_swift_struct(params[:key], params[:ios_output_paths].values.first, params[:cvs_output_path], params[:swift_struct_path])
25
+ end
26
+
27
+ if params[:dotnet_class_path]
28
+ self.create_dotnet_class(params[:key], params[:cvs_output_path], params[:dotnet_class_path])
29
+ end
30
+
31
+ File.delete(params[:cvs_output_path])
32
+ end
33
+
34
+ def self.convert_csv_to_ios_paths(key, cvs_path, output_paths)
35
+ output_paths.each do |file_path, index|
36
+ FileUtils.mkdir_p(File.dirname(file_path))
37
+ UI.message("Writing #{file_path}")
38
+ file = open(file_path, 'w')
39
+ CSV.foreach(cvs_path) do |row|
40
+ if row[key] && row[key].length > 0 && !row[index].nil?
41
+ key_row = row[key]
42
+ value_row = row[index].gsub("\"", "\\\"")
43
+ value_row = value_row.gsub("\n", "\\n")
44
+ file.write("#{key_row} = \"#{value_row}\";\n")
45
+ end
46
+ end
47
+ file.close
48
+ end
49
+ end
50
+
51
+ def self.convert_csv_to_android_paths(key, cvs_path, output_paths)
52
+ output_paths.each do |file_path, index|
53
+ FileUtils.mkdir_p(File.dirname(file_path))
54
+ UI.message("Writing #{file_path}")
55
+ file = open(file_path, 'w')
56
+ file.write("<resources>\n")
57
+ CSV.foreach(cvs_path) do |row|
58
+ if row[key] && row[key].length > 0
59
+ key_row = row[key]
60
+ file.write("\t<string name=\"#{key_row}\">#{row[index]}</string>\n")
61
+ end
62
+ end
63
+ file.write('</resources>')
64
+ file.close
65
+ end
66
+ end
67
+
68
+ def self.create_swift_struct(key, master_index, cvs_path, swift_path)
69
+ UI.message("Writing swift struct #{swift_path}")
70
+ FileUtils.mkdir_p(File.dirname(swift_path))
71
+ file = open(swift_path, 'w')
72
+ file.write("import Foundation\nstruct Translations {\n")
73
+
74
+ CSV.foreach(cvs_path) do |row|
75
+ if row[key] && row[key].length > 0 && row.compact.length > 1
76
+ key_row = row[key]
77
+ master = row[master_index]
78
+ parameters = master.scan(/\%\d+/)
79
+ if parameters.count > 0
80
+ args_str = parameters.map { |e| e.sub('%', 'p') + ': String' }.join(', _ ')
81
+ file.write("\tstatic func #{key_row}(_ #{args_str}) -> String {")
82
+ file.write(" return NSLocalizedString(\"#{key_row}\", comment: \"\")")
83
+ parameters.each { |e| file.write(".replacingOccurrences(of: \"#{e}\", with: #{e.sub('%', 'p')})") }
84
+ file.write(" }\n")
85
+ else
86
+ file.write("\tstatic let #{key_row} = NSLocalizedString(\"#{keyRow}\", comment: \"\");\n")
87
+ end
88
+ end
89
+ end
90
+ file.write("}")
91
+ file.close
92
+ end
93
+
94
+ def self.create_dotnet_class(key, cvs_path, dotnet_path)
95
+ UI.message("Writing dotnet struct #{dotnet_path}")
96
+ FileUtils.mkdir_p(File.dirname(dotnet_path))
97
+ file = open(dotnet_path, 'w')
98
+ file.write("using Foundation;\nstatic class Translations {\n")
99
+
100
+ CSV.foreach(cvs_path) do |row|
101
+ if row[key] && row[key].length > 0
102
+ key_row = row[key]
103
+ file.write("\tpublic static string #{key_row} { get { return NSBundle.MainBundle.LocalizedString (\"#{key_row}\", null); } }\n")
104
+ end
105
+ end
106
+ file.write("}")
107
+ file.close
108
+ end
109
+
110
+ #####################################################
111
+ # @!group Documentation
112
+ #####################################################
113
+
114
+ def self.description
115
+ "Output translations from Google sheet into templates."
116
+ end
117
+
118
+ def self.authors
119
+ ["Krzysztof Piatkowski", "Jakob Jensen"]
120
+ end
121
+
122
+ def self.return_value
123
+ end
124
+
125
+ def self.details
126
+ nil
127
+ end
128
+
129
+ def self.available_options
130
+ [
131
+ FastlaneCore::ConfigItem.new(key: :config_path,
132
+ env_name: "FL_TRANSLATION_CONFIG_PATH",
133
+ description: "refrence for the config json file, see https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md for more info",
134
+ optional: false),
135
+ FastlaneCore::ConfigItem.new(key: :doc_id,
136
+ env_name: "FL_TRANSLATION_DOC_ID",
137
+ description: "id of the google sheet, can be used instead of doc_name after creation",
138
+ optional: false),
139
+ FastlaneCore::ConfigItem.new(key: :cvs_output_path,
140
+ default_value: FastlaneCore::FastlaneFolder.path + "translation.cvs",
141
+ env_name: "FL_TRANSLATION_CVS_OUTPUT_PATH",
142
+ description: "The path where the cvs is placed",
143
+ optional: true),
144
+ FastlaneCore::ConfigItem.new(key: :ios_output_paths,
145
+ default_value: nil,
146
+ env_name: "FL_TRANSLATION_IOS_OUTPUT_PATH",
147
+ is_string: false,
148
+ description: "An map from path to a column in the google sheet outputs a localized .strings file",
149
+ optional: true),
150
+ FastlaneCore::ConfigItem.new(key: :android_output_paths,
151
+ default_value: nil,
152
+ env_name: "FL_TRANSLATION_ANDROID_OUTPUT_PATH",
153
+ is_string: false,
154
+ description: "An map from path to a column in the google sheet outputs a strings.xml",
155
+ optional: true),
156
+ FastlaneCore::ConfigItem.new(key: :swift_struct_path,
157
+ default_value: nil,
158
+ env_name: "FL_TRANSLATION_SWIFT_STRUCT_PATH",
159
+ is_string: false,
160
+ description: "Creates a swift struct with all the translations as properties",
161
+ optional: true),
162
+ FastlaneCore::ConfigItem.new(key: :dotnet_class_path,
163
+ default_value: nil,
164
+ env_name: "FL_TRANSLATION_DOTNET_CLASS_PATH",
165
+ is_string: false,
166
+ description: "Creates a .net class with all the translations as properties",
167
+ optional: true),
168
+ FastlaneCore::ConfigItem.new(key: :key,
169
+ default_value: 1,
170
+ is_string: false,
171
+ env_name: "FL_TRANSLATION_KEY",
172
+ description: "index of key column",
173
+ optional: true)
174
+ ]
175
+ end
176
+
177
+ def self.is_supported?(platform)
178
+ true
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,12 @@
1
+ module Fastlane
2
+ module Helper
3
+ class TranslationHelper
4
+ # class methods that you define here become available in your action
5
+ # as `Helper::TranslationsHelper.your_method`
6
+ #
7
+ def self.show_message
8
+ UI.message("Hello from the translation plugin helper!")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module Translation
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-translation
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jakob Jensen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: google-api-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.20
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.20
27
+ - !ruby/object:Gem::Dependency
28
+ name: google_drive
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.1.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.1.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.5.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.5.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: fastlane
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: 2.9.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: 2.9.0
139
+ description:
140
+ email: jje@trifork.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - lib/fastlane/plugin/translation/actions/create_translation_action.rb
146
+ - lib/fastlane/plugin/translation/actions/translation_action.rb
147
+ - lib/fastlane/plugin/translation/helper/translation_helper.rb
148
+ - lib/fastlane/plugin/translation/version.rb
149
+ - lib/fastlane/plugin/translation.rb
150
+ - README.md
151
+ - LICENSE
152
+ homepage: https://github.com/trifork/fastlane-plugin-translation
153
+ licenses:
154
+ - MIT
155
+ metadata: {}
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - '>='
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ requirements: []
171
+ rubyforge_project:
172
+ rubygems_version: 2.0.14.1
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: Handling translations from Google sheet.
176
+ test_files: []