locraft 1.2.0 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 00ea80f567e4b2549c83f9d7c405207eda4d3c23
4
- data.tar.gz: 86647c6f7d1980763c6f287aefb7ca220810fc5a
3
+ metadata.gz: 7cf55e11bdceb1841fb6634cdb0a7c542a007e84
4
+ data.tar.gz: 77890f235af48f9363d4f4137bf96b39ade76f6d
5
5
  SHA512:
6
- metadata.gz: 5cbb931ecf45f66c6ce3191b90c51a25344a7b8b27c28b410cf63ecd6fbb805fe71a0f899dec287244ed2387deaa029ea8c08fff6c98472c9f0209a9cb2384c4
7
- data.tar.gz: acd5d4ab92d6f3648a7629faa87178a47a7958925687c6a48a7a77856faf131d197aff1d1a6adf92ff87b57b18b072cdab49bcc64a1104cf9707a9e3b7b2f3d7
6
+ metadata.gz: 7eeb6f98a5128a0e1c841121e71ea079b8f8b0d839bb563ed22e455f1296770a0afa7c7233304c7508ec13fbeb16ddc218fba7c72bbc52b8b788abc83a47706e
7
+ data.tar.gz: 7e696aee22acb23c0327c507bb046c0d910f2f4ef5b4d549e9107a6d7e795cbddae27d2acf5eff4544e510a9ea7f8affec39a8aab34663f9290fe56a94f82e61
data/bin/locraft CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require File.expand_path('../../lib/locraft', __FILE__)
4
- Locraft::Runner.start(ARGV)
4
+ Locraft::Runner.start(ARGV)
@@ -6,7 +6,6 @@ module Locraft
6
6
  class Config
7
7
  attr_accessor :langs
8
8
  attr_accessor :default_lang
9
- attr_accessor :destination_dir
10
9
  attr_accessor :gdoc_file
11
10
  attr_accessor :gdoc_sheet
12
11
  attr_accessor :gdoc_keys_column
@@ -14,17 +13,16 @@ module Locraft
14
13
  attr_accessor :dev_lang
15
14
  attr_accessor :dev_prefix
16
15
  attr_accessor :macro_file
17
- attr_accessor :macro_destination_dir
16
+ attr_accessor :macro_destination
18
17
  attr_accessor :strings_basename
18
+ attr_accessor :strings_destination
19
19
  attr_accessor :info_plist_basename
20
+ attr_accessor :info_plist_destination
20
21
 
21
22
  # fill automatically in load_from method
22
23
  attr_accessor :from_file
23
24
 
24
25
  def initialize
25
- self.info_plist_basename = 'InfoPlist'
26
- self.strings_basename = 'Localizable'
27
- self.destination_dir = './Localizations'
28
26
  self.default_lang = 'English'
29
27
  self.gdoc_sheet = 0
30
28
  self.gdoc_keys_column = 'Keys'
@@ -32,7 +30,11 @@ module Locraft
32
30
  self.dev_lang = OBJC
33
31
  self.dev_prefix = 'XYZ'
34
32
  self.macro_file = 'LocalizedConstants'
35
- self.macro_destination_dir = './'
33
+ self.macro_destination = './'
34
+ self.strings_basename = 'Localizable'
35
+ self.strings_destination = './Localizations'
36
+ self.info_plist_basename = 'InfoPlist'
37
+ self.info_plist_destination = './Localizations'
36
38
  self.langs = {
37
39
  'English' => 'en',
38
40
  'Russian' => 'ru'
@@ -45,7 +47,7 @@ module Locraft
45
47
  begin
46
48
  config = eval(File.read(file), binding, 'config loading problem')
47
49
  config.from_file = file
48
- return config if Config === config
50
+ return config if config.is_a? Config
49
51
 
50
52
  warn "[#{file}] isn't a Locraft::Config, but #{config.class}."
51
53
  rescue SyntaxError, StandardError => e
@@ -53,12 +55,16 @@ module Locraft
53
55
  end
54
56
  end
55
57
 
56
- def relative_destination_dir
57
- File.expand_path('../' + destination_dir, from_file)
58
+ def relative_strings_destination
59
+ File.expand_path('../' + strings_destination, from_file)
60
+ end
61
+
62
+ def relative_plist_destination
63
+ File.expand_path('../' + info_plist_destination, from_file)
58
64
  end
59
65
 
60
- def relative_macro_destination_dir
61
- File.expand_path('../' + macro_destination_dir, from_file)
66
+ def relative_macro_destination
67
+ File.expand_path('../' + macro_destination, from_file)
62
68
  end
63
69
 
64
70
  def strings_file
@@ -1,35 +1,31 @@
1
1
  require_relative 'config'
2
+ require 'fileutils'
2
3
 
3
4
  module Locraft
4
5
  class ConstantsGenerator
6
+ include FileUtils
7
+
5
8
  OBJC_CONST_TEMPLATE_H = 'extern NSString *const __nonnull %{const};'
6
9
  OBJC_CONST_TEMPLATE_M = 'NSString *const %{const} = @"%{key}";'
7
10
  SWIFT_CONST_TEMPLATE = 'let %{const}: String = "%{key}"'
8
11
 
9
- def initialize(config)
12
+ def initialize(config, localizations)
10
13
  @config = config
14
+ @localizations = localizations
11
15
  end
12
16
 
13
17
  def generate
18
+ destination_dir = @config.relative_macro_destination
19
+ mkdir_p destination_dir unless Dir.exist?(destination_dir)
14
20
  if @config.dev_lang.equal?(OBJC)
15
- write_to("#{@config.relative_macro_destination_dir}/#{files_name}.h", h_file)
16
- write_to("#{@config.relative_macro_destination_dir}/#{files_name}.m", m_file)
21
+ write_to("#{destination_dir}/#{files_name}.h", h_file)
22
+ write_to("#{destination_dir}/#{files_name}.m", m_file)
17
23
  else
18
- write_to("#{@config.relative_macro_destination_dir}/#{files_name}.swift", swift_file)
24
+ write_to("#{destination_dir}/#{files_name}.swift", swift_file)
19
25
  end
20
-
21
26
  puts "constants files was created for [#{@config.dev_lang}] language"
22
27
  end
23
28
 
24
- def strings_lines
25
- File.readlines(strings_file).select { |l| l =~ /".*"\s*=\s*".*";/ }
26
- end
27
-
28
- def strings_file
29
- to_add = "#{@config.langs.values.first}.lproj/#{@config.strings_file}"
30
- File.join(@config.relative_destination_dir, to_add)
31
- end
32
-
33
29
  def write_to(file, content)
34
30
  File.open(file, 'w+') do |f|
35
31
  f.puts files_header + "\n"
@@ -61,9 +57,8 @@ module Locraft
61
57
  end
62
58
 
63
59
  def constants_keys
64
- strings_lines.map do |l|
65
- key = l.match(/"(.*)"\s*=/)[1]
66
- { key: key, const: constant_from(key) }
60
+ @localizations.select { |l| l.valid? }.map do |l|
61
+ { key: l.key, const: constant_from(l.key) }
67
62
  end
68
63
  end
69
64
 
@@ -1,65 +1,31 @@
1
1
  require_relative 'config'
2
+ require_relative 'localization'
2
3
  require 'csv'
3
- require 'fileutils'
4
4
 
5
5
  module Locraft
6
6
  class CSVParser
7
- include FileUtils
8
-
9
7
  def initialize(config)
10
8
  @config = config
11
9
  end
12
10
 
13
- def parse_csv_file_to_strings(csv_file)
14
- if File.file?(csv_file)
15
- parse_csv_to_strings(File.read(csv_file))
16
- else
17
- warn "CSVParser ERROR: there is no such a csv_file [#{csv_file}]"
18
- end
19
- end
20
-
21
- def parse_csv_to_strings(csv_body)
22
- rows = csv_rows(csv_body)
23
- @config.langs.keys.each do |lang|
24
- lproj_dir = mkdir_for_lang(lang)
25
- localizable_file = "#{lproj_dir}/#{@config.strings_file}"
26
- File.write(localizable_file, parse_rows_for_lang(rows, lang))
27
- end
28
- end
29
-
30
11
  def csv_rows(body)
31
12
  csv = CSV.new(body, headers: true)
32
13
  csv.to_a.map(&:to_hash)
33
14
  end
34
15
 
35
- # return strings file content
36
- def parse_rows_for_lang(rows, lang)
37
- content = ''
38
- rows.each do |row|
39
- hash = row_hash(row, lang)
40
- unless hash[:key].nil?
41
- content += '/* %{comment} */' % hash unless hash[:comment].nil?
42
- content += %(\n"%{key}" = "%{value}";\n\n) % hash
43
- end
16
+ # return localizations hash like #{ 'Lang' => [array of localizations] }
17
+ def parse_csv(csv_body)
18
+ rows = csv_rows(csv_body)
19
+ localizations_hash = {}
20
+ @config.langs.keys.each do |lang|
21
+ localizations_hash[lang] = parse_rows_for_lang(rows, lang)
44
22
  end
45
- content
23
+ localizations_hash
46
24
  end
47
25
 
48
- def row_hash(row, lang)
49
- value = row[lang] || row[@config.default_lang]
50
- key = row[@config.gdoc_keys_column] || row[@config.default_lang]
51
- comment = row[@config.gdoc_comments_column]
52
- {
53
- comment: comment&.strip,
54
- value: value&.strip,
55
- key: key&.strip
56
- }
57
- end
58
-
59
- def mkdir_for_lang(lang)
60
- lproj_dir = "#{@config.relative_destination_dir}/#{@config.langs[lang]}.lproj"
61
- mkdir_p lproj_dir unless Dir.exist?(lproj_dir)
62
- lproj_dir
26
+ # return localizations array
27
+ def parse_rows_for_lang(rows, lang)
28
+ rows.map { |row| Localization.load_with_csv_row(row, @config, lang) }
63
29
  end
64
30
  end
65
31
  end
@@ -2,6 +2,7 @@ require_relative 'config'
2
2
  require_relative 'csv_parser'
3
3
  require_relative 'info_plist_generator'
4
4
  require_relative 'constants_generator'
5
+ require_relative 'strings_generator'
5
6
  require_relative 'google_drive_wrapper'
6
7
 
7
8
  module Locraft
@@ -11,16 +12,29 @@ module Locraft
11
12
  end
12
13
 
13
14
  def extract
14
- # generate localized strings files
15
- csv_file = GoogleDriveWrapper.new(@config).export_worksheet
15
+ csv = GoogleDriveWrapper.new(@config).export_worksheet_csv
16
16
  csv_parser = CSVParser.new(@config)
17
- csv_parser.parse_csv_file_to_strings(csv_file)
17
+ localizations_hash = csv_parser.parse_csv(csv)
18
+ if localizations_hash[@config.default_lang].nil?
19
+ warn 'extract ERROR: no localizations given'
20
+ else
21
+ generate_strings(localizations_hash)
22
+ generate_info_plist(localizations_hash)
23
+ generate_constant(localizations_hash)
24
+ end
25
+ end
26
+
27
+ def generate_strings(localizations_hash)
28
+ StringsGenerator.new(@config, localizations_hash).generate
29
+ end
18
30
 
19
- # generate .plist files
20
- InfoPlistGenerator.new(@config).generate
31
+ def generate_info_plist(localizations_hash)
32
+ InfoPlistGenerator.new(@config, localizations_hash).generate
33
+ end
21
34
 
22
- # generate constants
23
- ConstantsGenerator.new(@config).generate
35
+ def generate_constant(localizations_hash)
36
+ localizations = localizations_hash[@config.default_lang]
37
+ ConstantsGenerator.new(@config, localizations).generate
24
38
  end
25
39
  end
26
40
  end
@@ -14,8 +14,8 @@ module Locraft
14
14
  end
15
15
 
16
16
  def authenticate
17
- mkdir_p @config.relative_destination_dir unless Dir.exist?(@config.relative_destination_dir)
18
- token_file = File.join(@config.relative_destination_dir, SESSION_TOKEN_FILE)
17
+ mkdir_p @config.relative_strings_destination unless Dir.exist?(@config.relative_strings_destination)
18
+ token_file = File.join(@config.relative_strings_destination, SESSION_TOKEN_FILE)
19
19
  @session = GoogleDrive.saved_session(token_file)
20
20
  end
21
21
 
@@ -24,18 +24,28 @@ module Locraft
24
24
  @session.spreadsheet_by_title(name)
25
25
  end
26
26
 
27
- # return exported file path
27
+ # return worksheet
28
28
  def export_worksheet
29
29
  worksheets = doc_named(@config.gdoc_file).worksheets
30
30
  if worksheets.count > @config.gdoc_sheet
31
- sheet = worksheets[@config.gdoc_sheet]
32
- file = File.join(@config.relative_destination_dir, EXPORTED_CSV_FILE)
33
- File.delete(file) if File.exist?(file)
34
- sheet.export_as_file(file)
35
- file
31
+ worksheets[@config.gdoc_sheet]
36
32
  else
37
33
  warn 'gdrive_wrapper worksheet export error: sheet number in config out of bounds!'
38
34
  end
39
35
  end
36
+
37
+ # return exported worksheet file path
38
+ def export_worksheet_file
39
+ sheet = export_worksheet
40
+ file = File.join(@config.relative_strings_destination, EXPORTED_CSV_FILE)
41
+ File.delete(file) if File.exist?(file)
42
+ sheet.export_as_file(file)
43
+ end
44
+
45
+ # return worksheet as string in csv format
46
+ def export_worksheet_csv
47
+ worksheet = export_worksheet
48
+ worksheet.export_as_string
49
+ end
40
50
  end
41
51
  end
@@ -1,28 +1,32 @@
1
1
  require_relative 'config'
2
+ require_relative 'localization'
3
+ require 'fileutils'
2
4
 
3
5
  module Locraft
4
6
  class InfoPlistGenerator
5
- def initialize(config)
7
+ include FileUtils
8
+
9
+ def initialize(config, localizations_hash)
6
10
  @config = config
11
+ @localizations_hash = localizations_hash
7
12
  end
8
13
 
9
14
  def generate
10
- dir = @config.relative_destination_dir
11
- folders = Dir.entries(dir).select { |d| d =~ /.+(.lproj)/ }.map { |d| File.join(dir, d) }
12
- folders.each { |f| generate_info_plist_in_lproj(f) }
13
- end
14
-
15
- def generate_info_plist_in_lproj(folder)
16
- localizable_file = File.join(folder, @config.strings_file.to_s)
17
- info_file = File.join(folder, @config.info_plist_file.to_s)
18
- File.write(info_file, info_plist_from(localizable_file))
19
-
20
- puts "- #{info_file} created"
15
+ @config.langs.each do |lang, val|
16
+ localizations = @localizations_hash[lang]
17
+ destination_dir = "#{@config.relative_plist_destination}/#{val}.lproj"
18
+ file = "#{destination_dir}/#{@config.info_plist_file}"
19
+ mkdir_p destination_dir unless Dir.exist?(destination_dir)
20
+ File.open(file, 'w+') do |f|
21
+ f.puts info_plist_with(localizations)
22
+ end
23
+ puts "info plist generated: [#{file}]"
24
+ end
21
25
  end
22
26
 
23
- def info_plist_from(localizable_file)
24
- filter = /"(?:NS|CF).*"\s*=\s*"[^;]*";/
25
- File.read(localizable_file).scan(filter).join("\n")
27
+ def info_plist_with(localizations)
28
+ filter = /(NS|CF).*/
29
+ localizations.select { |l| l.key =~ filter }.map(&:to_line).join("\n")
26
30
  end
27
31
  end
28
32
  end
@@ -0,0 +1,30 @@
1
+ module Locraft
2
+ class Localization
3
+ attr_accessor :language
4
+ attr_accessor :comment
5
+ attr_accessor :key
6
+ attr_accessor :value
7
+
8
+ def self.load_with_csv_row(row, config, lang)
9
+ localization = Localization.new
10
+ localization.language = lang
11
+ localization.comment = row[config.gdoc_comments_column]&.strip
12
+ localization.key = (row[config.gdoc_keys_column] || row[config.default_lang])&.strip
13
+ localization.value = (row[lang] || row[config.default_lang])&.strip
14
+ localization
15
+ end
16
+
17
+ def valid?
18
+ !(key.nil? or value.nil?)
19
+ end
20
+
21
+ def to_line
22
+ content = ''
23
+ if valid?
24
+ content += "/* #{comment} */" unless comment.nil?
25
+ content += %(\n"#{key}" = "#{value}";\n)
26
+ end
27
+ content
28
+ end
29
+ end
30
+ end
@@ -12,7 +12,6 @@ Locraft::Config.new do |conf|
12
12
  'Russian' => 'ru'
13
13
  } # default: {'English' => 'en', 'Russian' => 'ru'}
14
14
 
15
- conf.destination_dir = './Localizations' # strings destination directory related to this file, default: './Localizations'
16
15
  conf.default_lang = 'English' # default: 'English'
17
16
  conf.gdoc_sheet = 0 # default: 0
18
17
  conf.gdoc_keys_column = 'Keys' # default: 'Keys'
@@ -20,7 +19,9 @@ Locraft::Config.new do |conf|
20
19
  conf.dev_prefix = 'XYZ' # default: 'XYZ'
21
20
  conf.dev_lang = OBJC # OBJC or SWIFT, default: OBJC
22
21
  conf.macro_file = 'LocalizedConstants' # default: 'LocalizedConstants'
23
- conf.macro_destination_dir = './' # default: './'
22
+ conf.macro_destination = './' # default: './'
24
23
  conf.strings_basename = 'Localizable' # default: 'Localizable'
24
+ conf.strings_destination = './Localizations' # strings destination directory related to this file, default: './Localizations'
25
25
  conf.info_plist_basename = 'InfoPlist' # default: 'InfoPlist'
26
+ conf.info_plist_destination = './Localizations' # info plist destination directory related to this file, default: './Localizations'
26
27
  end
@@ -0,0 +1,31 @@
1
+ require_relative 'config'
2
+ require_relative 'localization'
3
+ require 'fileutils'
4
+
5
+ module Locraft
6
+ class StringsGenerator
7
+ include FileUtils
8
+
9
+ def initialize(config, localizations_hash)
10
+ @config = config
11
+ @localizations_hash = localizations_hash
12
+ end
13
+
14
+ def generate
15
+ @config.langs.each do |lang, val|
16
+ localizations = @localizations_hash[lang]
17
+ destination_dir = "#{@config.relative_strings_destination}/#{val}.lproj"
18
+ file = "#{destination_dir}/#{@config.strings_file}"
19
+ mkdir_p destination_dir unless Dir.exist?(destination_dir)
20
+ File.open(file, 'w+') do |f|
21
+ f.puts strings_file_with(localizations)
22
+ end
23
+ puts "strings file generated: [#{file}]"
24
+ end
25
+ end
26
+
27
+ def strings_file_with(localizations)
28
+ localizations.select { |l| l.valid? }.map(&:to_line).join("\n")
29
+ end
30
+ end
31
+ end
data/lib/locraft.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require_relative 'locraft/config'
2
+ require_relative 'locraft/localization'
2
3
  require_relative 'locraft/initializer'
3
4
  require_relative 'locraft/runner'
4
5
  require_relative 'locraft/extractor'
5
6
  require_relative 'locraft/info_plist_generator'
6
7
  require_relative 'locraft/constants_generator'
8
+ require_relative 'locraft/strings_generator'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locraft
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sroik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-06 00:00:00.000000000 Z
11
+ date: 2017-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google_drive
@@ -97,9 +97,11 @@ files:
97
97
  - lib/locraft/google_drive_wrapper.rb
98
98
  - lib/locraft/info_plist_generator.rb
99
99
  - lib/locraft/initializer.rb
100
+ - lib/locraft/localization.rb
100
101
  - lib/locraft/resources/constants_files_header.txt
101
102
  - lib/locraft/resources/sample_locraft.config
102
103
  - lib/locraft/runner.rb
104
+ - lib/locraft/strings_generator.rb
103
105
  homepage: https://github.com/app-craft/locraft
104
106
  licenses:
105
107
  - MIT