lokalise_rails 0.0.2.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8651b760040e8d699c07b833ee9225683a59816a7e17e8c045e8c3c57ab0c27
4
- data.tar.gz: 6f50abd924998842e093d6ceb2773a711428eb840ff95ca60a6b02b4dcd6aeef
3
+ metadata.gz: b8341e9150b8080050eb672077a415739178279e452ccad5d9f25bc7a24f83be
4
+ data.tar.gz: 4b6a74a12e62625d7bd6a41c8b46a93d029ef315551d4c6883375d9bf765aa72
5
5
  SHA512:
6
- metadata.gz: 30cfd51602a186da7f2986ce816ce4577412ae95a853111daf76ed62f8e1a57d0847b48e466cbefe6a5a6c978685bdbd6301eeb76c64ec92bbe06e5f962106d1
7
- data.tar.gz: 53c8154a59228d3795de7f53a326cf2a05fc892503744aaeed88a38a30cbf812a1156042f870590db5d9a21dd796f15975989b4c2ac98f98842a619ca1ab5d4e
6
+ metadata.gz: 13f5680ba0f8cfcd279929d7ab577712b1392760ca1d11460f6290d03d1ac9c4fe4915057656e3440cdda5a0958e5b230547549c9f2d4fe431c774fd7fe9ebd2
7
+ data.tar.gz: 4b98524742a8ed099f176351e073526db7e9fdae8e492318ac9f86c5b6ec8a7e650d9726a0b57571856e04a973e7aa9bcd7456aa9a6117e677d5039de33d1580
@@ -1,10 +1,19 @@
1
1
  # Changelog
2
2
 
3
- ## 0.0.2 (26-Sep-20)
3
+ ## 1.0.1 (14-Oct-20)
4
4
 
5
- * Fix rake task
6
- * Fix config template
5
+ * Minor bug fixes and spec updates
7
6
 
8
- ## 0.0.1 (26-Sep-20)
7
+ ## 1.0.0 (01-Oct-20)
9
8
 
10
- * Initial release
9
+ * Added export feature
10
+ * More convenient configuration and additional options
11
+ * Other major enhancements
12
+
13
+ ## 0.2.0 (26-Sep-20)
14
+
15
+ * Allow to override options properly
16
+
17
+ ## 0.1.0 (26-Sep-20)
18
+
19
+ * Initial (proper) release
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # LokaliseRails
2
2
 
3
- <!-- [![Gem Version](https://badge.fury.io/rb/ruby-lokalise-api.svg)](https://badge.fury.io/rb/ruby-lokalise-api) -->
3
+ [![Gem Version](https://badge.fury.io/rb/lokalise_rails.svg)](https://badge.fury.io/rb/lokalise_rails)
4
4
  [![Build Status](https://travis-ci.org/bodrovis/lokalise_rails.svg?branch=master)](https://travis-ci.org/bodrovis/lokalise_rails)
5
5
  [![Test Coverage](https://codecov.io/gh/bodrovis/lokalise_rails/graph/badge.svg)](https://codecov.io/gh/bodrovis/lokalise_rails)
6
6
 
@@ -10,34 +10,39 @@ This gem provides [Lokalise](http://lokalise.com) integration for Ruby on Rails
10
10
 
11
11
  ### Requirements
12
12
 
13
- This gem requires Ruby 2.5+ and Rails 5.1+. It might work with older versions of Rails though. You will also need to setup a Lokalise account and a translation project. Finally, you will need to generate a read/write API token at your Lokalise profile.
13
+ This gem requires Ruby 2.5+ and Rails 5.1+. It might work with older versions of Rails though. You will also need to [setup a Lokalise account](https://app.lokalise.com/signup) and create a [translation project](https://docs.lokalise.com/en/articles/1400460-projects). Finally, you will need to generate a [read/write API token](https://docs.lokalise.com/en/articles/1929556-api-tokens) at your Lokalise profile.
14
14
 
15
15
  ### Installation
16
16
 
17
- Add the gem to your `Gemfile`
17
+ Add the gem to your `Gemfile`:
18
18
 
19
19
  ```ruby
20
20
  gem 'lokalise_rails'
21
21
  ```
22
22
 
23
- and run
23
+ and run:
24
24
 
25
25
  ```
26
26
  bundle install
27
27
  rails g lokalise_rails:install
28
28
  ```
29
29
 
30
- The latter command will generate a new initializer `lokalise_rails.rb` looking like this:
30
+ The latter command will generate a new config file `config/lokalise_rails.rb` looking like this:
31
31
 
32
32
  ```ruby
33
33
  require 'lokalise_rails'
34
34
 
35
- LokaliseRails.api_token = ENV['LOKALISE_API_TOKEN']
36
- LokaliseRails.project_id = ENV['LOKALISE_PROJECT_ID']
37
- # ...
35
+ LokaliseRails.config do |c|
36
+ c.api_token = ENV['LOKALISE_API_TOKEN']
37
+ c.project_id = ENV['LOKALISE_PROJECT_ID']
38
+
39
+ # ...other options
40
+ end
38
41
  ```
39
42
 
40
- You have to provide `api_token` and `project_id` to proceed. [Other options can be customized as well (see below)](https://github.com/bodrovis/lokalise_rails#import-settings) but they have sensible defaults.
43
+ You have to provide `api_token` and `project_id` to proceed. `project_id` can be found in your Lokalise project settings.
44
+
45
+ [Other options can be customized as well (see below)](https://github.com/bodrovis/lokalise_rails#import-settings) but they have sensible defaults.
41
46
 
42
47
  ## Importing translations from Lokalise
43
48
 
@@ -47,31 +52,46 @@ To import translations from the specified Lokalise project to your Rails app, ru
47
52
  rails lokalise_rails:import
48
53
  ```
49
54
 
50
- Please note that any existing files inside the `locales` directory will be overwritten! You may enable [safe mode](https://github.com/bodrovis/lokalise_rails#import-settings) to check whether the folder is empty or not.
55
+ Please note that any duplicating files inside the `locales` directory (or any other directory that you've specified in the options) will be overwritten! You may enable [safe mode](https://github.com/bodrovis/lokalise_rails#import-settings) to check whether the folder is empty or not.
51
56
 
52
- ## Configuration
57
+ ## Exporting translations to Lokalise
53
58
 
54
- Options are specified in the `config/initializers/lokalise_rails.rb` file.
59
+ To export translations from your Rails app to the specified Lokalise project, run the following command:
55
60
 
56
- ### Global settings
61
+ ```
62
+ rails lokalise_rails:export
63
+ ```
57
64
 
58
- * `LokaliseRails.api_token` (`string`, required) - Lokalise API token with read/write permissions.
59
- * `LokaliseRails.project_id` (`string`, required) - Lokalise project ID. You must have import/export permissions in the specified project.
60
- * `locales_path` - method returning a string with the path to your translation files. Defaults to `"#{Rails.root}/config/locales"`. To provide a custom path, override the method inside the initializer (make sure that the path exists!):
65
+ ## Running tasks programmatically
66
+
67
+ You can also run the import and export tasks from the Rails app:
61
68
 
62
69
  ```ruby
63
- class LokaliseRails
64
- class << self
65
- def locales_path
66
- "#{Rails.root}/config/locales_custom"
67
- end
68
- end
69
- end
70
+ require "#{Rails.root}/config/lokalise_rails.rb"
71
+
72
+ # Import the files:
73
+ result = LokaliseRails::TaskDefinition::Importer.import!
74
+ # `result` contains a boolean value with the result of the operation
75
+
76
+ # Export the files:
77
+ processes = LokaliseRails::TaskDefinition::Exporter.export!
78
+ # `processes` contains a list of queued background processes
70
79
  ```
71
80
 
81
+ ## Configuration
82
+
83
+ Options are specified in the `config/lokalise_rails.rb` file.
84
+
85
+ ### Global settings
86
+
87
+ * `api_token` (`string`, required) - Lokalise API token with read/write permissions.
88
+ * `project_id` (`string`, required) - Lokalise project ID. You must have import/export permissions in the specified project.
89
+ * `locales_path` (`string`) - path to the directory with your translation files. Defaults to `"#{Rails.root}/config/locales"`.
90
+ * `file_ext_regexp` (`regexp`) - regular expression applied to file extensions to determine which files should be imported and exported. Defaults to `/\.ya?ml\z/i` (YAML files).
91
+
72
92
  ### Import settings
73
93
 
74
- * `LokaliseRails.import_opts` (`hash`) - options that will be passed to Lokalise API when downloading translations to your app. Here are the default options:
94
+ * `import_opts` (`hash`) - options that will be passed to Lokalise API when downloading translations to your app. Here are the default options:
75
95
 
76
96
  ```ruby
77
97
  {
@@ -84,8 +104,33 @@ end
84
104
  }
85
105
  ```
86
106
 
87
- Full list of available options [can be found at the official API documentation](https://app.lokalise.com/api2docs/curl/#transition-download-files-post).
88
- * `LokaliseRails.import_safe_mode` (`boolean`) - default to `false`. When this option is enabled, the import task will check whether the `locales` directory is empty or not. If it is not empty, you will be prompted to continue.
107
+ Full list of available import options [can be found in the official API documentation](https://app.lokalise.com/api2docs/curl/#transition-download-files-post).
108
+ * `import_safe_mode` (`boolean`) - default to `false`. When this option is enabled, the import task will check whether the directory set with `locales_path` is empty or not. If it is not empty, you will be prompted to continue.
109
+
110
+ ### Export settings
111
+
112
+ * `export_opts` (`hash`) - options that will be passed to Lokalise API when uploading translations. Full list of available export options [can be found in the official documentation](https://app.lokalise.com/api2docs/curl/#transition-download-files-post). By default, the following options are provided:
113
+ + `data` (`string`, required) - base64-encoded contents of the translation file.
114
+ + `filename` (`string`, required) - translation file name. If the file is stored under a subdirectory (for example, `nested/en.yml` inside the `locales/` directory), the whole path acts as a name. Later when importing files with such names, they will be placed into the proper subdirectories.
115
+ + `lang_iso` (`string`, required) - language ISO code which is determined using the root key inside your YAML file. For example, in this case the `lang_iso` is `en_US`:
116
+
117
+ ```yaml
118
+ en_US:
119
+ my_key: "my value"
120
+ ```
121
+
122
+ **Please note** that if your Lokalise project does not have a language with the specified `lang_iso` code, the export will fail.
123
+
124
+ * `skip_file_export` (`lambda` or `proc`) - specify additional exclusion criteria for the exported files. By default, the rake task will ignore all non-file entries and all files with improper extensions (the latter is controlled by the `file_ext_regexp`). Lambda passed to this option should accept a single argument which is full path to the file (instance of the [`Pathname` class](https://ruby-doc.org/stdlib-2.7.1/libdoc/pathname/rdoc/Pathname.html)). For example, to exclude all files that have `fr` part in their names, add the following config:
125
+
126
+ ```ruby
127
+ c.skip_file_export = ->(file) { f.split[1].to_s.include?('fr') }
128
+ ```
129
+
130
+ ## Running tests
131
+
132
+ 1. Copypaste `.env.example` file as `.env`. Put your Lokalise API token and project ID inside. The `.env` file is excluded from version control so your data is safe. All in all, we use pre-recorded VCR cassettes, so the actual API requests won’t be sent. However, providing at least some values is required.
133
+ 2. Run `rspec .`. Observe test results and code coverage.
89
134
 
90
135
  ## License
91
136
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'rails/generators'
4
4
 
5
- class LokaliseRails
5
+ module LokaliseRails
6
6
  module Generators
7
7
  class InstallGenerator < Rails::Generators::Base
8
8
  source_root File.expand_path('../templates', __dir__)
@@ -10,7 +10,7 @@ class LokaliseRails
10
10
  desc 'Creates a LokaliseRails config file.'
11
11
 
12
12
  def copy_config
13
- template 'lokalise_rails_config.rb', "#{Rails.root}/config/initializers/lokalise_rails.rb"
13
+ template 'lokalise_rails_config.rb', "#{Rails.root}/config/lokalise_rails.rb"
14
14
  end
15
15
  end
16
16
  end
@@ -2,28 +2,33 @@
2
2
 
3
3
  require 'lokalise_rails'
4
4
 
5
- # These are mandatory options that you must set before running rake tasks:
6
- LokaliseRails.api_token = ENV['LOKALISE_API_TOKEN']
7
- LokaliseRails.project_id = ENV['LOKALISE_PROJECT_ID']
8
-
9
- # Import options have the following defaults:
10
- # LokaliseRails.import_opts = {
11
- # format: 'yaml',
12
- # placeholder_format: :icu,
13
- # yaml_include_root: true,
14
- # original_filenames: true,
15
- # directory_prefix: '',
16
- # indentation: '2sp'
17
- # }
18
-
19
- # Safe mode is disabled by default:
20
- # LokaliseRails.import_safe_mode = false
21
-
22
- # Provide a custom path to the directory with your translation files:
23
- # class LokaliseRails
24
- # class << self
25
- # def locales_path
26
- # "#{Rails.root}/config/locales"
27
- # end
28
- # end
29
- # end
5
+ LokaliseRails.config do |c|
6
+ # These are mandatory options that you must set before running rake tasks:
7
+ # c.api_token = ENV['LOKALISE_API_TOKEN']
8
+ # c.project_id = ENV['LOKALISE_PROJECT_ID']
9
+
10
+ # Provide a custom path to the directory with your translation files:
11
+ # c.locales_path = "#{Rails.root}/config/locales"
12
+
13
+ # Import options have the following defaults:
14
+ # c.import_opts = {
15
+ # format: 'yaml',
16
+ # placeholder_format: :icu,
17
+ # yaml_include_root: true,
18
+ # original_filenames: true,
19
+ # directory_prefix: '',
20
+ # indentation: '2sp'
21
+ # }
22
+
23
+ # Safe mode for imports is disabled by default:
24
+ # c.import_safe_mode = false
25
+
26
+ # Additional export options (only filename, contents, and lang_iso params are provided by default)
27
+ # c.export_opts = {}
28
+
29
+ # Provide additional file exclusion criteria for exports (by default, any file with the proper extension will be exported)
30
+ # c.skip_file_export = ->(file) { file.split[1].to_s.include?('fr') }
31
+
32
+ # Regular expression to use when choosing the files to extract from the downloaded archive and upload to Lokalise
33
+ # c.file_ext_regexp = /\.ya?ml\z/i
34
+ end
@@ -2,29 +2,54 @@
2
2
 
3
3
  require 'lokalise_rails/task_definition/base'
4
4
  require 'lokalise_rails/task_definition/importer'
5
+ require 'lokalise_rails/task_definition/exporter'
5
6
 
6
- class LokaliseRails
7
- @project_id = nil
8
- @import_opts = {
9
- format: 'yaml',
10
- placeholder_format: :icu,
11
- yaml_include_root: true,
12
- original_filenames: true,
13
- directory_prefix: '',
14
- indentation: '2sp'
15
- }
16
- # @export_opts = {
17
- #
18
- # }
19
- @import_safe_mode = false
20
- @api_token = nil
21
-
7
+ module LokaliseRails
22
8
  class << self
23
- attr_accessor :import_opts, :import_safe_mode, :api_token, :export_opts,
24
- :project_id
9
+ attr_accessor :api_token, :project_id
10
+ attr_writer :import_opts, :import_safe_mode, :export_opts, :locales_path,
11
+ :file_ext_regexp, :skip_file_export
12
+
13
+ # Main interface to provide configuration options for rake tasks
14
+ def config
15
+ yield self
16
+ end
25
17
 
18
+ # Full path to directory with translation files
26
19
  def locales_path
27
- "#{Rails.root}/config/locales"
20
+ @locales_path || "#{Rails.root}/config/locales"
21
+ end
22
+
23
+ # Regular expression used to select translation files with proper extensions
24
+ def file_ext_regexp
25
+ @file_ext_regexp || /\.ya?ml\z/i
26
+ end
27
+
28
+ # Options for import rake task
29
+ def import_opts
30
+ @import_opts || {
31
+ format: 'yaml',
32
+ placeholder_format: :icu,
33
+ yaml_include_root: true,
34
+ original_filenames: true,
35
+ directory_prefix: '',
36
+ indentation: '2sp'
37
+ }
38
+ end
39
+
40
+ # Options for export rake task
41
+ def export_opts
42
+ @export_opts || {}
43
+ end
44
+
45
+ # Enables safe mode for import. When enabled, will check whether the target folder is empty or not
46
+ def import_safe_mode
47
+ @import_safe_mode.nil? ? false : @import_safe_mode
48
+ end
49
+
50
+ # Additional file skip criteria to apply when performing export
51
+ def skip_file_export
52
+ @skip_file_export || ->(_) { false }
28
53
  end
29
54
  end
30
55
  end
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rubygems'
4
3
  require 'rake'
5
4
 
6
- class LokaliseRails
5
+ module LokaliseRails
7
6
  class Railtie < Rails::Railtie
8
7
  rake_tasks do
9
- load "tasks/lokalise_rails_tasks.rake"
8
+ load 'tasks/lokalise_rails_tasks.rake'
10
9
  end
11
10
  end
12
11
  end
@@ -1,17 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'ruby-lokalise-api'
4
- require 'open-uri'
4
+ require 'pathname'
5
5
 
6
- class LokaliseRails
6
+ module LokaliseRails
7
7
  module TaskDefinition
8
8
  class Base
9
9
  class << self
10
- def check_required_opts
11
- return [false, 'Project ID is not set! Aborting...'] unless LokaliseRails.project_id
12
- return [false, 'Lokalise API token is not set! Aborting...'] unless LokaliseRails.api_token
10
+ attr_writer :api_client
13
11
 
14
- [true, '']
12
+ # Creates a Lokalise API client
13
+ #
14
+ # @return [Lokalise::Client]
15
+ def api_client
16
+ @api_client ||= ::Lokalise.client LokaliseRails.api_token
17
+ end
18
+
19
+ # Checks task options
20
+ #
21
+ # @return Array
22
+ def opt_errors
23
+ errors = []
24
+ errors << 'Project ID is not set! Aborting...' if LokaliseRails.project_id.nil? || LokaliseRails.project_id.empty?
25
+ errors << 'Lokalise API token is not set! Aborting...' if LokaliseRails.api_token.nil? || LokaliseRails.api_token.empty?
26
+ errors
27
+ end
28
+
29
+ private
30
+
31
+ # Checks whether the provided file has a proper extension as dictated by the `file_ext_regexp` option
32
+ #
33
+ # @return Boolean
34
+ # @param raw_path [String, Pathname]
35
+ def proper_ext?(raw_path)
36
+ path = raw_path.is_a?(Pathname) ? raw_path : Pathname.new(raw_path)
37
+ LokaliseRails.file_ext_regexp.match? path.extname
38
+ end
39
+
40
+ # Returns directory and filename for the given entry
41
+ #
42
+ # @return Array
43
+ # @param entry [String]
44
+ def subdir_and_filename_for(entry)
45
+ Pathname.new(entry).split
15
46
  end
16
47
  end
17
48
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module LokaliseRails
6
+ module TaskDefinition
7
+ class Exporter < Base
8
+ class << self
9
+ # Performs translation file export from Rails to Lokalise and returns an array of queued processes
10
+ #
11
+ # @return [Array]
12
+ def export!
13
+ errors = opt_errors
14
+
15
+ if errors.any?
16
+ errors.each { |e| $stdout.puts e }
17
+ return errors
18
+ end
19
+
20
+ queued_processes = []
21
+ each_file do |full_path, relative_path|
22
+ queued_processes << api_client.upload_file(
23
+ LokaliseRails.project_id, opts(full_path, relative_path)
24
+ )
25
+ rescue StandardError => e
26
+ $stdout.puts "Error while trying to upload #{full_path}: #{e.inspect}"
27
+ end
28
+
29
+ $stdout.print 'Task complete!'
30
+
31
+ queued_processes
32
+ end
33
+
34
+ # Processes each translation file in the specified directory
35
+ def each_file
36
+ return unless block_given?
37
+
38
+ loc_path = LokaliseRails.locales_path
39
+ Dir["#{loc_path}/**/*"].sort.each do |f|
40
+ full_path = Pathname.new f
41
+
42
+ next unless file_matches_criteria? full_path
43
+
44
+ relative_path = full_path.relative_path_from Pathname.new(loc_path)
45
+
46
+ yield full_path, relative_path
47
+ end
48
+ end
49
+
50
+ # Generates export options
51
+ #
52
+ # @return [Hash]
53
+ # @param full_p [Pathname]
54
+ # @param relative_p [Pathname]
55
+ def opts(full_p, relative_p)
56
+ content = File.read full_p
57
+
58
+ lang_iso = YAML.safe_load(content)&.keys&.first
59
+
60
+ initial_opts = {
61
+ data: Base64.strict_encode64(content.strip),
62
+ filename: relative_p,
63
+ lang_iso: lang_iso
64
+ }
65
+
66
+ initial_opts.merge LokaliseRails.export_opts
67
+ end
68
+
69
+ # Checks whether the specified file has to be processed or not
70
+ #
71
+ # @return [Boolean]
72
+ # @param full_path [Pathname]
73
+ def file_matches_criteria?(full_path)
74
+ full_path.file? && proper_ext?(full_path) &&
75
+ !LokaliseRails.skip_file_export.call(full_path)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end