lokalise_rails 0.0.2.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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