poeditor-cli 0.1.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: c3981c762a561c1d20ae5e66b5f200f00a2e3e6b
4
+ data.tar.gz: adfdd3ff5b171bc1d4098af35299e87d677bb086
5
+ SHA512:
6
+ metadata.gz: 21c12379f59d9d8bfd10c4f56e5f22c6c230906cf9053d0ab358247ed46db22ef3d2d088623ebd35ccb249f20f8d8e5ad903811f374f96bcc8435b3af8ad3bfd
7
+ data.tar.gz: 8cd8959d0dec9bd5e33b962ecb493fe75d936df16eac5bda2d9dff3e41afdb624e7bbd24781986c1dc8d69d39a23b4af89072c7529702a22118f06ad63f9310e
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Suyeol Jeon (xoul.kr)
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,50 @@
1
+ # poeditor-cli
2
+
3
+ [![Gem](https://img.shields.io/gem/v/cocoaseeds.svg)](https://rubygems.org/gems/cocoaseeds)
4
+ [![Build Status](https://travis-ci.org/StyleShare/poeditor-cli.svg?branch=master)](https://travis-ci.org/StyleShare/poeditor-cli)
5
+
6
+ Command line application for [POEditor](https://poeditor.com).
7
+
8
+ <img width="682" alt="poeditor-cli" src="https://cloud.githubusercontent.com/assets/931655/22509884/2aebebc2-e8d3-11e6-86e2-a9915ca755b5.png">
9
+
10
+ ## Usage
11
+
12
+ 1. **Create `poeditor.yml` file**
13
+
14
+ Here is an example.
15
+
16
+ ```yaml
17
+ api_key: YOUR_API_KEY
18
+ project_id: PROJECT_ID
19
+ languages: [en, ko, jp, zh-Hans, zh-Hant, fr, es]
20
+ path: example/Resources/{LANGUAGE}.lproj/Localizable.strings
21
+ type: apple_strings
22
+ tags: [ios] # optional
23
+ ```
24
+
25
+ | Field | Description |
26
+ |---|---|
27
+ | `api_key` | Your POEditor API key. You can check it on [POEditor API Access](https://poeditor.com/account/api). |
28
+ | `project_id` | POEditor project ID. You can check this value on the web browser's address bar.<br />For example: `https://poeditor.com/projects/view?id=XXXXX` |
29
+ | `languages` | Language codes to export. Use your project's language code.<br />For example, use `zh-Hans` if you're working on Xcode project even though POEditor uses `zh-CN` for simplified chinese. |
30
+ | `path` | The path for translation files to be downloaded. Each values of `languages` will be used for filling `{LANGUAGE}` placeholder. |
31
+ | `type` | Translation file format. (po, pot, mo, xls, csv, resw, resx, android_strings, apple_strings, xliff, properties, key_value_json, json, xmb, xtb) |
32
+ | `tags` | (Optional) Terms which contain whole tags will be exported. (`&&`) |
33
+
34
+ 2. **Export using CLI**
35
+
36
+ ```console
37
+ $ poeditor export
38
+ ```
39
+
40
+ 3. **You're done! 🎉**
41
+
42
+ ## Installation
43
+
44
+ ```console
45
+ $ [sudo] gem install poeditor-cli
46
+ ```
47
+
48
+ ## License
49
+
50
+ **poeditor-cli** is written by [Suyeol Jeon](https://github.com/devxoul) and available under MIT license.
data/bin/poeditor ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "poeditor"
4
+
5
+ POEditor::Command.run(ARGV)
data/lib/poeditor.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "colorize"
2
+ require "fileutils"
3
+ require "shellwords"
4
+ require "yaml"
5
+
6
+ module POEditor
7
+ autoload :Version, "poeditor/version"
8
+ autoload :Exception, "poeditor/exception"
9
+ autoload :UI, "poeditor/ui"
10
+
11
+ # core
12
+ autoload :Exporter, "poeditor/core/exporter"
13
+ autoload :Formatter, "poeditor/core/formatter"
14
+
15
+ # command
16
+ autoload :Command, "poeditor/commands/command"
17
+ autoload :ExportCommand, "poeditor/commands/export_command"
18
+ autoload :HelpCommand, "poeditor/commands/help_command"
19
+ autoload :VersionCommand, "poeditor/commands/version_command"
20
+
21
+ # configuration
22
+ autoload :ExportConfiguration, "poeditor/configurations/export_configuration"
23
+ end
@@ -0,0 +1,25 @@
1
+ module POEditor
2
+ class Command
3
+ # The entry point of the CLI application
4
+ def self.run(argv)
5
+ UI.enabled = true
6
+ command = self.command_class(argv).new
7
+ begin
8
+ command.run(argv)
9
+ rescue POEditor::Exception => e
10
+ puts "[!] #{e.message}".red
11
+ end
12
+ end
13
+
14
+ def self.command_class(argv)
15
+ case argv[0]
16
+ when "export"
17
+ ExportCommand
18
+ when "--version"
19
+ VersionCommand
20
+ else
21
+ HelpCommand
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,64 @@
1
+ module POEditor
2
+ class ExportCommand
3
+ def run(argv)
4
+ UI.puts "Reading configuration"
5
+ configuration = get_configuration(argv)
6
+ UI.puts configuration
7
+ exporter = POEditor::Exporter.new(configuration)
8
+ exporter.export_all()
9
+ end
10
+
11
+ # Detects and returns the location of `poeditor.yml` file from the given
12
+ # system arguments.
13
+ #
14
+ # @param argv [Array<String>] System arguments
15
+ #
16
+ # @return [String] The detected path of `poeditor.yml` file
17
+ def get_configuration_file_path(argv)
18
+ config_index = argv.index("-c") or argv.index("--config")
19
+ if config_index
20
+ config_path = argv[config_index + 1]
21
+ else
22
+ config_path = "poeditor.yml"
23
+ end
24
+ end
25
+
26
+ # Returns {#POEditor::ExportConfiguration} from the given system arguments.
27
+ #
28
+ # @param argv [Array<String>] System arguments
29
+ #
30
+ # @return [POEditor::ExportConfiguration] The export configuration
31
+ def get_configuration(argv)
32
+ config_path = get_configuration_file_path(argv)
33
+ unless File.exist?(config_path)
34
+ raise POEditor::Exception.new %{\
35
+ Configuration file doesn't exist: #{config_path}.
36
+ Try creating `poeditor.yml` or specifying the path using '--config'.\
37
+ }
38
+ end
39
+ yaml = YAML.load(File.read(config_path))
40
+ ExportConfiguration.new(
41
+ api_key: get_or_raise(yaml, "api_key"),
42
+ project_id: get_or_raise(yaml, "project_id"),
43
+ languages: get_or_raise(yaml, "languages"),
44
+ type: get_or_raise(yaml, "type"),
45
+ tags: yaml["tags"],
46
+ path: get_or_raise(yaml, "path"),
47
+ )
48
+ end
49
+
50
+ # Returns the value of specified key from the given yaml instance. Raise
51
+ # exception when there's no key in the yaml.
52
+ #
53
+ # @param yaml [YAML]
54
+ # @param key [String]
55
+ #
56
+ # @return The value for the specified key from yaml
57
+ # @raise [POEditor::Exception]
58
+ def get_or_raise(yaml, key)
59
+ yaml[key] or raise POEditor::Exception.new \
60
+ "Missing configuration key: '#{key}'"
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ module POEditor
2
+ class HelpCommand
3
+ def run(argv)
4
+ puts "Usage: poeditor export"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module POEditor
2
+ class VersionCommand
3
+ def run(argv)
4
+ puts POEditor::VERSION
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,46 @@
1
+ module POEditor
2
+ class ExportConfiguration
3
+ # @return [String] POEditor API key
4
+ # @see https://poeditor.com/account/api POEditor API Access
5
+ attr_accessor :api_key
6
+
7
+ # @return [String] POEditor project ID
8
+ attr_accessor :project_id
9
+
10
+ # @return [Array<String>] The languages codes
11
+ attr_accessor :languages
12
+
13
+ # @return [String] Export file type (po, apple_strings, android_strings)
14
+ attr_accessor :type
15
+
16
+ # @return [Array<String>] Tag filters (optional)
17
+ attr_accessor :tags
18
+
19
+ attr_accessor :path
20
+
21
+ def initialize(api_key:, project_id:, languages:, type:, tags:nil, path:)
22
+ @api_key = api_key
23
+ @project_id = project_id
24
+ @languages = languages
25
+ @type = type
26
+ @tags = tags or []
27
+ @path = path
28
+ end
29
+
30
+ def default_path(type)
31
+ Formatter.cls(type).default_path
32
+ end
33
+
34
+ def to_s
35
+ values = {
36
+ "api_key" => self.api_key,
37
+ "project_id" => self.project_id,
38
+ "languages" => self.languages,
39
+ "type" => self.type,
40
+ "tags" => self.tags,
41
+ "path" => self.path,
42
+ }
43
+ values.map { |key, value| " - #{key}: #{value}" }.join "\n"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,96 @@
1
+ require "json"
2
+ require "net/http"
3
+
4
+ module POEditor
5
+ class Exporter
6
+ # @return [POEditor::ExportConfiguration] The configuration for export
7
+ attr_accessor :configuration
8
+
9
+ # @param configuration [POEditor::ExportConfiguration]
10
+ def initialize(configuration)
11
+ unless configuration.is_a? ExportConfiguration
12
+ raise POEditor::Exception.new \
13
+ "`configuration` should be an `ExportConfiguration`"
14
+ end
15
+ @configuration = configuration
16
+ end
17
+
18
+ # Request POEditor API
19
+ #
20
+ # @param action [String]
21
+ # @param api_token [String]
22
+ # @param options [Hash{Sting => Object}]
23
+ #
24
+ # @return [Net::HTTPResponse] The response object of API request
25
+ #
26
+ # @see https://poeditor.com/api_reference/ POEditor API Reference
27
+ def api(action, api_token, options={})
28
+ uri = URI("https://poeditor.com/api/")
29
+ options["action"] = action
30
+ options["api_token"] = api_token
31
+ return Net::HTTP.post_form(uri, options)
32
+ end
33
+
34
+ # Exports all translations
35
+ def export_all()
36
+ UI.puts "\nExport translations"
37
+ for language in @configuration.languages
38
+ UI.puts " - Exporting '#{language}'"
39
+ content = self.export(:api_key => @configuration.api_key,
40
+ :project_id => @configuration.project_id,
41
+ :language => language,
42
+ :type => @configuration.type,
43
+ :tags => @configuration.tags)
44
+ Formatter.write(@configuration.path, language, content)
45
+ end
46
+ end
47
+
48
+ # Export translation for specific language
49
+ #
50
+ # @param api_key [String]
51
+ # @param project_jd [String]
52
+ # @param language [String]
53
+ # @param type [String]
54
+ # @param tags [Array<String>]
55
+ #
56
+ # @return Downloaded translation content
57
+ def export(api_key:, project_id:, language:, type:, tags:nil)
58
+ options = {
59
+ "id" => project_id,
60
+ "language" => convert_to_poeditor_language(language),
61
+ "type" => type,
62
+ "tags" => (tags or []).join(","),
63
+ }
64
+ response = self.api("export", api_key, options)
65
+ data = JSON(response.body)
66
+ unless data["response"]["status"] == "success"
67
+ code = data["response"]["code"]
68
+ message = data["response"]["message"]
69
+ raise POEditor::Exception.new "#{message} (#{code})"
70
+ end
71
+
72
+ download_uri = URI(data["item"])
73
+ content = Net::HTTP.get(download_uri)
74
+
75
+ case type
76
+ when "apple_strings"
77
+ content.gsub!(/(%(\d+\$)?)s/, '\1@') # %s -> %@
78
+ when "android_strings"
79
+ content.gsub!(/(%(\d+\$)?)@/, '\1s') # %@ -> %s
80
+ end
81
+
82
+ return content
83
+ end
84
+
85
+ def convert_to_poeditor_language(language)
86
+ if language.downcase.match(/zh.+hans/)
87
+ 'zh-CN'
88
+ elsif language.downcase.match(/zh.+hant/)
89
+ 'zh-TW'
90
+ else
91
+ language
92
+ end
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,16 @@
1
+ module POEditor
2
+ class Formatter
3
+ def self.build_path(path_template, language)
4
+ path_template.gsub "{LANGUAGE}", language
5
+ end
6
+
7
+ def self.write(path_template, language, content)
8
+ path = build_path(path_template, language)
9
+ unless File.exist?(path)
10
+ raise POEditor::Exception.new "#{path} doesn't exist"
11
+ end
12
+ File.write(path, content)
13
+ UI.puts " #{"\xe2\x9c\x93".green} Saved at '#{path}'"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module POEditor
2
+ class Exception < Exception
3
+ end
4
+ end
@@ -0,0 +1,17 @@
1
+ module POEditor
2
+ class UI
3
+ @@enabled = false
4
+
5
+ def self.enabled
6
+ @@enabled
7
+ end
8
+
9
+ def self.enabled=enabled
10
+ @@enabled = enabled
11
+ end
12
+
13
+ def self.puts(*args)
14
+ Kernel.puts args.map { |x| x.to_s }.join(" ") if @@enabled
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module POEditor
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: poeditor-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Suyeol Jeon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.8'
27
+ description: POEditor CLI
28
+ email: devxoul@gmail.com
29
+ executables:
30
+ - poeditor
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE
35
+ - README.md
36
+ - bin/poeditor
37
+ - lib/poeditor.rb
38
+ - lib/poeditor/commands/command.rb
39
+ - lib/poeditor/commands/export_command.rb
40
+ - lib/poeditor/commands/help_command.rb
41
+ - lib/poeditor/commands/version_command.rb
42
+ - lib/poeditor/configurations/export_configuration.rb
43
+ - lib/poeditor/core/exporter.rb
44
+ - lib/poeditor/core/formatter.rb
45
+ - lib/poeditor/exception.rb
46
+ - lib/poeditor/ui.rb
47
+ - lib/poeditor/version.rb
48
+ homepage: https://github.com/devxoul/poeditor-cli
49
+ licenses:
50
+ - MIT
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.5.1
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: POEditor CLI
72
+ test_files: []