lokalise_rails 2.0.0 → 5.0.0
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 +4 -4
- data/CHANGELOG.md +43 -0
- data/Gemfile +12 -1
- data/README.md +74 -57
- data/lib/generators/lokalise_rails/install_generator.rb +2 -0
- data/lib/generators/templates/lokalise_rails_config.rb +2 -4
- data/lib/lokalise_rails/global_config.rb +12 -0
- data/lib/lokalise_rails/railtie.rb +1 -0
- data/lib/lokalise_rails/utils.rb +23 -0
- data/lib/lokalise_rails/version.rb +3 -1
- data/lib/lokalise_rails.rb +8 -88
- data/lib/tasks/lokalise_rails_tasks.rake +6 -3
- data/lokalise_rails.gemspec +7 -18
- data/spec/dummy/config/lokalise_rails.rb +3 -3
- data/spec/lib/generators/lokalise_rails/install_generator_spec.rb +2 -2
- data/spec/lib/{lokalise_rails_spec.rb → lokalise_rails/global_config_spec.rb} +17 -5
- data/spec/lib/lokalise_rails/version_spec.rb +7 -0
- data/spec/lib/tasks/export_task_spec.rb +25 -18
- data/spec/lib/tasks/import_task_spec.rb +36 -99
- data/spec/lib/utils_spec.rb +16 -0
- data/spec/spec_helper.rb +0 -2
- data/spec/support/file_manager.rb +8 -11
- data/spec/support/spec_addons.rb +8 -3
- metadata +21 -178
- data/lib/lokalise_rails/error.rb +0 -10
- data/lib/lokalise_rails/task_definition/base.rb +0 -80
- data/lib/lokalise_rails/task_definition/exporter.rb +0 -79
- data/lib/lokalise_rails/task_definition/importer.rb +0 -109
- data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/dummy/config/initializers/content_security_policy.rb +0 -29
- data/spec/dummy/config/initializers/inflections.rb +0 -17
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
- data/spec/lib/lokalise_rails/task_definition/base_spec.rb +0 -81
- data/spec/lib/lokalise_rails/task_definition/exporter_spec.rb +0 -200
- data/spec/lib/lokalise_rails/task_definition/importer_spec.rb +0 -72
- data/spec/support/rake_utils.rb +0 -15
@@ -1,80 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'ruby-lokalise-api'
|
4
|
-
require 'pathname'
|
5
|
-
|
6
|
-
module LokaliseRails
|
7
|
-
module TaskDefinition
|
8
|
-
class Base
|
9
|
-
class << self
|
10
|
-
attr_writer :api_client
|
11
|
-
|
12
|
-
# Creates a Lokalise API client
|
13
|
-
#
|
14
|
-
# @return [Lokalise::Client]
|
15
|
-
def api_client
|
16
|
-
@api_client ||= ::Lokalise.client LokaliseRails.api_token, {enable_compression: true}.merge(LokaliseRails.timeouts)
|
17
|
-
end
|
18
|
-
|
19
|
-
# Resets API client
|
20
|
-
def reset_api_client!
|
21
|
-
Lokalise.reset_client!
|
22
|
-
@api_client = nil
|
23
|
-
end
|
24
|
-
|
25
|
-
# Checks task options
|
26
|
-
#
|
27
|
-
# @return Array
|
28
|
-
def check_options_errors!
|
29
|
-
errors = []
|
30
|
-
errors << 'Project ID is not set!' if LokaliseRails.project_id.nil? || LokaliseRails.project_id.empty?
|
31
|
-
errors << 'Lokalise API token is not set!' if LokaliseRails.api_token.nil? || LokaliseRails.api_token.empty?
|
32
|
-
|
33
|
-
raise(LokaliseRails::Error, errors.join(' ')) if errors.any?
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
# Checks whether the provided file has a proper extension as dictated by the `file_ext_regexp` option
|
39
|
-
#
|
40
|
-
# @return Boolean
|
41
|
-
# @param raw_path [String, Pathname]
|
42
|
-
def proper_ext?(raw_path)
|
43
|
-
path = raw_path.is_a?(Pathname) ? raw_path : Pathname.new(raw_path)
|
44
|
-
LokaliseRails.file_ext_regexp.match? path.extname
|
45
|
-
end
|
46
|
-
|
47
|
-
# Returns directory and filename for the given entry
|
48
|
-
#
|
49
|
-
# @return Array
|
50
|
-
# @param entry [String]
|
51
|
-
def subdir_and_filename_for(entry)
|
52
|
-
Pathname.new(entry).split
|
53
|
-
end
|
54
|
-
|
55
|
-
# Returns Lokalise project ID and branch, semicolumn separated
|
56
|
-
#
|
57
|
-
# @return [String]
|
58
|
-
def project_id_with_branch
|
59
|
-
"#{LokaliseRails.project_id}:#{LokaliseRails.branch}"
|
60
|
-
end
|
61
|
-
|
62
|
-
# Sends request with exponential backoff mechanism
|
63
|
-
def with_exp_backoff(max_retries)
|
64
|
-
return unless block_given?
|
65
|
-
|
66
|
-
retries = 0
|
67
|
-
begin
|
68
|
-
yield
|
69
|
-
rescue Lokalise::Error::TooManyRequests => e
|
70
|
-
raise(e.class, "Gave up after #{retries} retries") if retries >= max_retries
|
71
|
-
|
72
|
-
sleep 2**retries
|
73
|
-
retries += 1
|
74
|
-
retry
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
@@ -1,79 +0,0 @@
|
|
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
|
-
check_options_errors!
|
14
|
-
|
15
|
-
queued_processes = []
|
16
|
-
each_file do |full_path, relative_path|
|
17
|
-
queued_processes << do_upload(full_path, relative_path)
|
18
|
-
rescue StandardError => e
|
19
|
-
raise e.class, "Error while trying to upload #{full_path}: #{e.message}"
|
20
|
-
end
|
21
|
-
|
22
|
-
$stdout.print 'Task complete!'
|
23
|
-
|
24
|
-
queued_processes
|
25
|
-
end
|
26
|
-
|
27
|
-
# Performs the actual file uploading to Lokalise. If the API rate limit is exceeed,
|
28
|
-
# applies exponential backoff
|
29
|
-
def do_upload(f_path, r_path)
|
30
|
-
with_exp_backoff(LokaliseRails.max_retries_export) do
|
31
|
-
api_client.upload_file project_id_with_branch, opts(f_path, r_path)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Processes each translation file in the specified directory
|
36
|
-
def each_file
|
37
|
-
return unless block_given?
|
38
|
-
|
39
|
-
loc_path = LokaliseRails.locales_path
|
40
|
-
Dir["#{loc_path}/**/*"].sort.each do |f|
|
41
|
-
full_path = Pathname.new f
|
42
|
-
|
43
|
-
next unless file_matches_criteria? full_path
|
44
|
-
|
45
|
-
relative_path = full_path.relative_path_from Pathname.new(loc_path)
|
46
|
-
|
47
|
-
yield full_path, relative_path
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Generates export options
|
52
|
-
#
|
53
|
-
# @return [Hash]
|
54
|
-
# @param full_p [Pathname]
|
55
|
-
# @param relative_p [Pathname]
|
56
|
-
def opts(full_p, relative_p)
|
57
|
-
content = File.read full_p
|
58
|
-
|
59
|
-
initial_opts = {
|
60
|
-
data: Base64.strict_encode64(content.strip),
|
61
|
-
filename: relative_p,
|
62
|
-
lang_iso: LokaliseRails.lang_iso_inferer.call(content)
|
63
|
-
}
|
64
|
-
|
65
|
-
initial_opts.merge LokaliseRails.export_opts
|
66
|
-
end
|
67
|
-
|
68
|
-
# Checks whether the specified file has to be processed or not
|
69
|
-
#
|
70
|
-
# @return [Boolean]
|
71
|
-
# @param full_path [Pathname]
|
72
|
-
def file_matches_criteria?(full_path)
|
73
|
-
full_path.file? && proper_ext?(full_path) &&
|
74
|
-
!LokaliseRails.skip_file_export.call(full_path)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'zip'
|
4
|
-
require 'yaml'
|
5
|
-
require 'open-uri'
|
6
|
-
require 'fileutils'
|
7
|
-
|
8
|
-
module LokaliseRails
|
9
|
-
module TaskDefinition
|
10
|
-
class Importer < Base
|
11
|
-
class << self
|
12
|
-
# Performs translation files import from Lokalise to Rails app
|
13
|
-
#
|
14
|
-
# @return [Boolean]
|
15
|
-
def import!
|
16
|
-
check_options_errors!
|
17
|
-
|
18
|
-
unless proceed_when_safe_mode?
|
19
|
-
$stdout.print 'Task cancelled!'
|
20
|
-
return false
|
21
|
-
end
|
22
|
-
|
23
|
-
open_and_process_zip download_files['bundle_url']
|
24
|
-
|
25
|
-
$stdout.print 'Task complete!'
|
26
|
-
true
|
27
|
-
end
|
28
|
-
|
29
|
-
# Downloads files from Lokalise using the specified options.
|
30
|
-
# Utilizes exponential backoff if "too many requests" error is received
|
31
|
-
#
|
32
|
-
# @return [Hash]
|
33
|
-
def download_files
|
34
|
-
with_exp_backoff(LokaliseRails.max_retries_import) do
|
35
|
-
api_client.download_files project_id_with_branch, LokaliseRails.import_opts
|
36
|
-
end
|
37
|
-
rescue StandardError => e
|
38
|
-
raise e.class, "There was an error when trying to download files: #{e.message}"
|
39
|
-
end
|
40
|
-
|
41
|
-
# Opens ZIP archive (local or remote) with translations and processes its entries
|
42
|
-
#
|
43
|
-
# @param path [String]
|
44
|
-
def open_and_process_zip(path)
|
45
|
-
Zip::File.open_buffer(open_file_or_remote(path)) do |zip|
|
46
|
-
fetch_zip_entries(zip) { |entry| process!(entry) }
|
47
|
-
end
|
48
|
-
rescue StandardError => e
|
49
|
-
raise e.class, "There was an error when trying to process the downloaded files: #{e.message}"
|
50
|
-
end
|
51
|
-
|
52
|
-
# Iterates over ZIP entries. Each entry may be a file or folder.
|
53
|
-
def fetch_zip_entries(zip)
|
54
|
-
return unless block_given?
|
55
|
-
|
56
|
-
zip.each do |entry|
|
57
|
-
next unless proper_ext? entry.name
|
58
|
-
|
59
|
-
yield entry
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Processes ZIP entry by reading its contents and creating the corresponding translation file
|
64
|
-
def process!(zip_entry)
|
65
|
-
data = data_from zip_entry
|
66
|
-
subdir, filename = subdir_and_filename_for zip_entry.name
|
67
|
-
full_path = "#{LokaliseRails.locales_path}/#{subdir}"
|
68
|
-
FileUtils.mkdir_p full_path
|
69
|
-
|
70
|
-
File.open(File.join(full_path, filename), 'w+:UTF-8') do |f|
|
71
|
-
f.write LokaliseRails.translations_converter.call(data)
|
72
|
-
end
|
73
|
-
rescue StandardError => e
|
74
|
-
raise e.class, "Error when trying to process #{zip_entry&.name}: #{e.message}"
|
75
|
-
end
|
76
|
-
|
77
|
-
# Checks whether the user wishes to proceed when safe mode is enabled and the target directory is not empty
|
78
|
-
#
|
79
|
-
# @return [Boolean]
|
80
|
-
def proceed_when_safe_mode?
|
81
|
-
return true unless LokaliseRails.import_safe_mode && !Dir.empty?(LokaliseRails.locales_path.to_s)
|
82
|
-
|
83
|
-
$stdout.puts "The target directory #{LokaliseRails.locales_path} is not empty!"
|
84
|
-
$stdout.print 'Enter Y to continue: '
|
85
|
-
answer = $stdin.gets
|
86
|
-
answer.to_s.strip == 'Y'
|
87
|
-
end
|
88
|
-
|
89
|
-
# Opens a local file or a remote URL using the provided patf
|
90
|
-
#
|
91
|
-
# @return [String]
|
92
|
-
def open_file_or_remote(path)
|
93
|
-
parsed_path = URI.parse(path)
|
94
|
-
if parsed_path&.scheme&.include?('http')
|
95
|
-
parsed_path.open
|
96
|
-
else
|
97
|
-
File.open path
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
def data_from(zip_entry)
|
104
|
-
LokaliseRails.translations_loader.call zip_entry.get_input_stream.read
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
@@ -1,8 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
# Be sure to restart your server when you modify this file.
|
3
|
-
|
4
|
-
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
5
|
-
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
6
|
-
|
7
|
-
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
8
|
-
# Rails.backtrace_cleaner.remove_silencers!
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
# Be sure to restart your server when you modify this file.
|
3
|
-
|
4
|
-
# Define an application-wide content security policy
|
5
|
-
# For further information see the following documentation
|
6
|
-
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
|
7
|
-
|
8
|
-
# Rails.application.config.content_security_policy do |policy|
|
9
|
-
# policy.default_src :self, :https
|
10
|
-
# policy.font_src :self, :https, :data
|
11
|
-
# policy.img_src :self, :https, :data
|
12
|
-
# policy.object_src :none
|
13
|
-
# policy.script_src :self, :https
|
14
|
-
# policy.style_src :self, :https
|
15
|
-
|
16
|
-
# # Specify URI for violation reports
|
17
|
-
# # policy.report_uri "/csp-violation-report-endpoint"
|
18
|
-
# end
|
19
|
-
|
20
|
-
# If you are using UJS then enable automatic nonce generation
|
21
|
-
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
|
22
|
-
|
23
|
-
# Set the nonce only to specific directives
|
24
|
-
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
|
25
|
-
|
26
|
-
# Report CSP violations to a specified URI
|
27
|
-
# For further information see the following documentation:
|
28
|
-
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
|
29
|
-
# Rails.application.config.content_security_policy_report_only = true
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
# Be sure to restart your server when you modify this file.
|
3
|
-
|
4
|
-
# Add new inflection rules using the following format. Inflections
|
5
|
-
# are locale specific, and you may define rules for as many different
|
6
|
-
# locales as you wish. All of these examples are active by default:
|
7
|
-
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
8
|
-
# inflect.plural /^(ox)$/i, '\1en'
|
9
|
-
# inflect.singular /^(ox)en/i, '\1'
|
10
|
-
# inflect.irregular 'person', 'people'
|
11
|
-
# inflect.uncountable %w( fish sheep )
|
12
|
-
# end
|
13
|
-
|
14
|
-
# These inflection rules are supported but not enabled by default:
|
15
|
-
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
16
|
-
# inflect.acronym 'RESTful'
|
17
|
-
# end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Be sure to restart your server when you modify this file.
|
4
|
-
|
5
|
-
# This file contains settings for ActionController::ParamsWrapper which
|
6
|
-
# is enabled by default.
|
7
|
-
|
8
|
-
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
9
|
-
ActiveSupport.on_load(:action_controller) do
|
10
|
-
wrap_parameters format: [:json]
|
11
|
-
end
|
12
|
-
|
13
|
-
# To enable root element in JSON for ActiveRecord objects.
|
14
|
-
# ActiveSupport.on_load(:active_record) do
|
15
|
-
# self.include_root_in_json = true
|
16
|
-
# end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe LokaliseRails::TaskDefinition::Base do
|
4
|
-
specify '.reset_client!' do
|
5
|
-
expect(described_class.api_client).to be_an_instance_of(Lokalise::Client)
|
6
|
-
described_class.reset_api_client!
|
7
|
-
current_client = described_class.instance_variable_get '@api_client'
|
8
|
-
expect(current_client).to be_nil
|
9
|
-
end
|
10
|
-
|
11
|
-
specify '.project_id_with_branch!' do
|
12
|
-
result = described_class.send :project_id_with_branch
|
13
|
-
expect(result).to be_an_instance_of(String)
|
14
|
-
expect(result).to include(':master')
|
15
|
-
end
|
16
|
-
|
17
|
-
describe '.subdir_and_filename_for' do
|
18
|
-
it 'works properly for longer paths' do
|
19
|
-
path = 'my_path/is/here/file.yml'
|
20
|
-
result = described_class.send(:subdir_and_filename_for, path)
|
21
|
-
expect(result.length).to eq(2)
|
22
|
-
expect(result[0]).to be_an_instance_of(Pathname)
|
23
|
-
expect(result[0].to_s).to eq('my_path/is/here')
|
24
|
-
expect(result[1].to_s).to eq('file.yml')
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'works properly for shorter paths' do
|
28
|
-
path = 'file.yml'
|
29
|
-
result = described_class.send(:subdir_and_filename_for, path)
|
30
|
-
expect(result.length).to eq(2)
|
31
|
-
expect(result[1]).to be_an_instance_of(Pathname)
|
32
|
-
expect(result[0].to_s).to eq('.')
|
33
|
-
expect(result[1].to_s).to eq('file.yml')
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe '.check_options_errors!' do
|
38
|
-
it 'raises an error when the API key is not set' do
|
39
|
-
allow(LokaliseRails).to receive(:api_token).and_return(nil)
|
40
|
-
|
41
|
-
expect(-> { described_class.check_options_errors! }).to raise_error(LokaliseRails::Error, /API token is not set/i)
|
42
|
-
|
43
|
-
expect(LokaliseRails).to have_received(:api_token)
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'returns an error when the project_id is not set' do
|
47
|
-
allow_project_id nil do
|
48
|
-
expect(-> { described_class.check_options_errors! }).to raise_error(LokaliseRails::Error, /ID is not set/i)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe '.proper_ext?' do
|
54
|
-
it 'works properly with path represented as a string' do
|
55
|
-
path = 'my_path/here/file.yml'
|
56
|
-
expect(described_class.send(:proper_ext?, path)).to be true
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'works properly with path represented as a pathname' do
|
60
|
-
path = Pathname.new 'my_path/here/file.json'
|
61
|
-
expect(described_class.send(:proper_ext?, path)).to be false
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe '.api_client' do
|
66
|
-
before(:all) { described_class.reset_api_client! }
|
67
|
-
|
68
|
-
after(:all) { described_class.reset_api_client! }
|
69
|
-
|
70
|
-
it 'is possible to set timeouts' do
|
71
|
-
allow(LokaliseRails).to receive(:timeouts).and_return({
|
72
|
-
open_timeout: 100,
|
73
|
-
timeout: 500
|
74
|
-
})
|
75
|
-
|
76
|
-
expect(described_class.api_client).to be_an_instance_of(Lokalise::Client)
|
77
|
-
expect(described_class.api_client.open_timeout).to eq(100)
|
78
|
-
expect(described_class.api_client.timeout).to eq(500)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
@@ -1,200 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'base64'
|
4
|
-
|
5
|
-
describe LokaliseRails::TaskDefinition::Exporter do
|
6
|
-
let(:filename) { 'en.yml' }
|
7
|
-
let(:path) { "#{Rails.root}/config/locales/nested/#{filename}" }
|
8
|
-
let(:relative_name) { "nested/#{filename}" }
|
9
|
-
|
10
|
-
context 'with many translation files' do
|
11
|
-
let(:fake_class) { described_class }
|
12
|
-
|
13
|
-
before :all do
|
14
|
-
add_translation_files! with_ru: true, additional: 5
|
15
|
-
end
|
16
|
-
|
17
|
-
after :all do
|
18
|
-
rm_translation_files
|
19
|
-
end
|
20
|
-
|
21
|
-
describe '.export!' do
|
22
|
-
it 'sends a proper API request and handles rate limiting' do
|
23
|
-
allow_project_id '672198945b7d72fc048021.15940510'
|
24
|
-
|
25
|
-
process = VCR.use_cassette('upload_files_multiple') do
|
26
|
-
described_class.export!
|
27
|
-
end.first
|
28
|
-
|
29
|
-
expect(process.project_id).to eq(LokaliseRails.project_id)
|
30
|
-
expect(process.status).to eq('queued')
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'handles too many requests' do
|
34
|
-
allow_project_id '672198945b7d72fc048021.15940510'
|
35
|
-
allow(LokaliseRails).to receive(:max_retries_export).and_return(2)
|
36
|
-
|
37
|
-
fake_client = double
|
38
|
-
allow(fake_client).to receive(:upload_file).and_raise(Lokalise::Error::TooManyRequests)
|
39
|
-
allow(fake_class).to receive(:api_client).and_return(fake_client)
|
40
|
-
|
41
|
-
expect(-> { fake_class.export! }).to raise_error(Lokalise::Error::TooManyRequests, /Gave up after 2 retries/i)
|
42
|
-
expect(LokaliseRails).to have_received(:max_retries_export).exactly(1).times
|
43
|
-
expect(fake_class).to have_received(:api_client).exactly(3).times
|
44
|
-
expect(fake_client).to have_received(:upload_file).exactly(3).times
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
context 'with one translation file' do
|
50
|
-
before :all do
|
51
|
-
add_translation_files!
|
52
|
-
end
|
53
|
-
|
54
|
-
after :all do
|
55
|
-
rm_translation_files
|
56
|
-
end
|
57
|
-
|
58
|
-
describe '.export!' do
|
59
|
-
it 'sends a proper API request' do
|
60
|
-
allow_project_id
|
61
|
-
|
62
|
-
process = VCR.use_cassette('upload_files') do
|
63
|
-
described_class.export!
|
64
|
-
end.first
|
65
|
-
|
66
|
-
expect(process.project_id).to eq(LokaliseRails.project_id)
|
67
|
-
expect(process.status).to eq('queued')
|
68
|
-
expect(LokaliseRails.max_retries_export).to eq(5)
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'sends a proper API request when a different branch is provided' do
|
72
|
-
allow_project_id
|
73
|
-
allow(LokaliseRails).to receive(:branch).and_return('develop')
|
74
|
-
|
75
|
-
process = VCR.use_cassette('upload_files_branch') do
|
76
|
-
described_class.export!
|
77
|
-
end.first
|
78
|
-
|
79
|
-
expect(LokaliseRails).to have_received(:branch)
|
80
|
-
expect(process.project_id).to eq(LokaliseRails.project_id)
|
81
|
-
expect(process.status).to eq('queued')
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'halts when the API key is not set' do
|
85
|
-
allow(LokaliseRails).to receive(:api_token).and_return(nil)
|
86
|
-
|
87
|
-
expect(-> { described_class.export! }).to raise_error(LokaliseRails::Error, /API token is not set/i)
|
88
|
-
expect(LokaliseRails).to have_received(:api_token)
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'halts when the project_id is not set' do
|
92
|
-
allow_project_id nil do
|
93
|
-
expect(-> { described_class.export! }).to raise_error(LokaliseRails::Error, /ID is not set/i)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
describe '.each_file' do
|
99
|
-
it 'yield proper arguments' do
|
100
|
-
expect { |b| described_class.each_file(&b) }.to yield_with_args(
|
101
|
-
Pathname.new(path),
|
102
|
-
Pathname.new(relative_name)
|
103
|
-
)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe '.opts' do
|
108
|
-
let(:base64content) { Base64.strict_encode64(File.read(path).strip) }
|
109
|
-
|
110
|
-
it 'generates proper options' do
|
111
|
-
resulting_opts = described_class.opts(path, relative_name)
|
112
|
-
|
113
|
-
expect(resulting_opts[:data]).to eq(base64content)
|
114
|
-
expect(resulting_opts[:filename]).to eq(relative_name)
|
115
|
-
expect(resulting_opts[:lang_iso]).to eq('en')
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'allows to redefine options' do
|
119
|
-
allow(LokaliseRails).to receive(:export_opts).and_return({
|
120
|
-
detect_icu_plurals: true,
|
121
|
-
convert_placeholders: true
|
122
|
-
})
|
123
|
-
|
124
|
-
resulting_opts = described_class.opts(path, relative_name)
|
125
|
-
|
126
|
-
expect(LokaliseRails).to have_received(:export_opts)
|
127
|
-
expect(resulting_opts[:data]).to eq(base64content)
|
128
|
-
expect(resulting_opts[:filename]).to eq(relative_name)
|
129
|
-
expect(resulting_opts[:lang_iso]).to eq('en')
|
130
|
-
expect(resulting_opts[:detect_icu_plurals]).to be true
|
131
|
-
expect(resulting_opts[:convert_placeholders]).to be true
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context 'with two translation files' do
|
137
|
-
let(:filename_ru) { 'ru.yml' }
|
138
|
-
let(:path_ru) { "#{Rails.root}/config/locales/#{filename_ru}" }
|
139
|
-
let(:relative_name_ru) { filename_ru }
|
140
|
-
|
141
|
-
before :all do
|
142
|
-
add_translation_files! with_ru: true
|
143
|
-
end
|
144
|
-
|
145
|
-
after :all do
|
146
|
-
rm_translation_files
|
147
|
-
end
|
148
|
-
|
149
|
-
describe '.export!' do
|
150
|
-
it 're-raises export errors' do
|
151
|
-
allow_project_id
|
152
|
-
|
153
|
-
VCR.use_cassette('upload_files_error') do
|
154
|
-
expect { described_class.export! }.to raise_error(Lokalise::Error::BadRequest, /Unknown `lang_iso`/)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
describe '.opts' do
|
160
|
-
let(:base64content_ru) { Base64.strict_encode64(File.read(path_ru).strip) }
|
161
|
-
|
162
|
-
it 'generates proper options' do
|
163
|
-
resulting_opts = described_class.opts(path_ru, relative_name_ru)
|
164
|
-
|
165
|
-
expect(resulting_opts[:data]).to eq(base64content_ru)
|
166
|
-
expect(resulting_opts[:filename]).to eq(relative_name_ru)
|
167
|
-
expect(resulting_opts[:lang_iso]).to eq('ru_RU')
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
describe '.each_file' do
|
172
|
-
it 'yields every translation file' do
|
173
|
-
expect { |b| described_class.each_file(&b) }.to yield_successive_args(
|
174
|
-
[
|
175
|
-
Pathname.new(path),
|
176
|
-
Pathname.new(relative_name)
|
177
|
-
],
|
178
|
-
[
|
179
|
-
Pathname.new(path_ru),
|
180
|
-
Pathname.new(relative_name_ru)
|
181
|
-
]
|
182
|
-
)
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'does not yield files that have to be skipped' do
|
186
|
-
allow(LokaliseRails).to receive(:skip_file_export).twice.and_return(
|
187
|
-
->(f) { f.split[1].to_s.include?('ru') }
|
188
|
-
)
|
189
|
-
expect { |b| described_class.each_file(&b) }.to yield_successive_args(
|
190
|
-
[
|
191
|
-
Pathname.new(path),
|
192
|
-
Pathname.new(relative_name)
|
193
|
-
]
|
194
|
-
)
|
195
|
-
|
196
|
-
expect(LokaliseRails).to have_received(:skip_file_export).twice
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|