neeto-translate-cli 0.1.8 → 0.2.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: cb434279a1de983aa87756bcc1417772548a8e8a917cb5fdc78502cb00e3e66e
4
- data.tar.gz: 5d3d5f98971d257304b1fce67d02187223cd692f97bc0a34cd7ede2babab4518
3
+ metadata.gz: 3342ceff58e0e24877a5ad0295522d9b4021cdd2e4072222a2ca857c44c4967c
4
+ data.tar.gz: 4176f99987bac93f0ab622f9fd6aca88c76d4b3e9baff0f98bb1b28830a6bd2a
5
5
  SHA512:
6
- metadata.gz: 0d4f2f9f216bedf499006d886b69ce16d2140238b007054e17fda8aa08487044b8cd2414f5a68c1954bde394d4de1a7618b4a3aaa6cf10bbb2ca87ec97002def
7
- data.tar.gz: 8485944b91dafaa1e583741304b6fd3508eff19ee5662a8e640e1ff51ed32ec9381e9112732f1db31c442d36f2281c22cb32bad83ca3470afb6eb641ad1d004e
6
+ metadata.gz: d441b82773afcba86cfd7343f5660269de975127fbef6b3136fbf6f659d3e048b5a51fa7f39ecfa9dfdf2983937425166f09cf7fe8537a70962ed8d2b4c98de3
7
+ data.tar.gz: dbf6d4caf8ba255ae07d24539d231610c8a378e62185a295dd98cbce53d53c11d2d375ee4cecb10639089a5fb465c289ce788d76f7411cf06efc4975beb12aea
@@ -31,7 +31,8 @@ module NeetoTranslateCli
31
31
  frontend: DEFAULT_FRONTEND_LOCALE_PATH,
32
32
  backend: DEFAULT_BACKEND_LOCALE_PATH,
33
33
  default_languages: (ENV["DEFAULT_LANGUAGES"] || DEFAULT_LANGUAGES).to_s.split(","),
34
- repo: `git rev-parse --show-toplevel`.split("/").last.strip
34
+ repo: `git rev-parse --show-toplevel`.split("/").last.strip,
35
+ branch: "main"
35
36
  }
36
37
 
37
38
  OptionParser.new do |opts|
@@ -43,6 +44,11 @@ module NeetoTranslateCli
43
44
  opts.on("--repo NAME", "Name of the GitHub repository (eg: neetozone/neeto-cal-web).") do |path|
44
45
  options[:repo] = path
45
46
  end
47
+ opts.on("--branch NAME", "Base branch to which the PR should be created") { |branch| options[:branch] = branch}
48
+
49
+ # This arg is explicitly added to handle translations in neeto-website and bigbinary-website.
50
+ # Usage: --strategy next-i18next
51
+ opts.on("--strategy NAME", "Name of the i18next package used to generate the translations") { |name| options[:strategy] = name }
46
52
  end.parse!(args)
47
53
 
48
54
  options
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+
5
+ module NeetoTranslateCli
6
+ module NextI18next
7
+ class PayloadBuilder
8
+ attr_reader :options, :updated_keys
9
+
10
+ def initialize(options)
11
+ @options = options
12
+ commit_id = git_commit_id
13
+ @updated_keys = commit_id.empty? ? { frontend: {} } : find_updated_keys(commit_id)
14
+ end
15
+
16
+ def process!
17
+ {
18
+ frontend: {
19
+ en: flatten_hash_with_colon(frontend_translations[:en]),
20
+ missing_keys: find_missing_keys
21
+ },
22
+ metadata: {
23
+ repo: options[:repo],
24
+ frontend: options[:frontend],
25
+ strategy: options[:strategy],
26
+ branch: options[:branch]
27
+ }
28
+ }
29
+ end
30
+
31
+ def no_new_changes?(payload)
32
+ payload[:frontend][:missing_keys].values.all?(&:empty?)
33
+ end
34
+
35
+ private
36
+
37
+ def git_commit_id
38
+ `git log --grep="[neeto-translate]" --fixed-strings -n 1 --pretty=format:"%H"`.strip
39
+ end
40
+
41
+ def find_updated_keys(commit_id)
42
+ updated_frontend_keys = {}
43
+ frontend_translations[:en].each do |file_path, content|
44
+ lang_file_path = "#{options[:frontend]}/en/#{file_path}.json"
45
+ relative_path_from_pwd = Pathname.new(lang_file_path).to_s
46
+ previous_content = `git show #{commit_id}:#{relative_path_from_pwd}`
47
+ next if previous_content.empty?
48
+
49
+ previous_json = JSON.parse(previous_content)
50
+ flat_previous_json = flatten_hash(previous_json)
51
+ flat_current_json = flatten_hash(content)
52
+
53
+ updated_keys_for_file = flat_current_json.keys.select do |key|
54
+ flat_previous_json.key?(key) && flat_current_json[key] != flat_previous_json[key]
55
+ end
56
+
57
+ next if updated_keys_for_file.empty?
58
+
59
+ updated_frontend_keys[lang_file_path] = updated_keys_for_file
60
+ end
61
+ { frontend: updated_frontend_keys }
62
+ end
63
+
64
+ def find_missing_keys
65
+ missing_keys = {}
66
+ base_translations = frontend_translations[:en]
67
+
68
+ options[:default_languages].each do |lang|
69
+ missing_keys[lang] = []
70
+ base_translations.each do |base_file_path, base_content|
71
+ lang_file_path = "#{options[:frontend]}/#{lang}/#{base_file_path}.json"
72
+
73
+ base_keys = flatten_hash(base_content).keys
74
+ lang_keys = File.file?(lang_file_path) ? flatten_hash(load_json(lang_file_path)).keys : []
75
+
76
+ missing_in_file = (base_keys - lang_keys).uniq
77
+ missing_keys[lang].concat(missing_in_file.map { |key| "#{base_file_path}:#{key}" })
78
+ end
79
+ end
80
+
81
+ missing_keys
82
+ end
83
+
84
+ def frontend_translations
85
+ return @_frontend_translations if defined?(@_frontend_translations)
86
+
87
+ all_files = Dir.glob("#{options[:frontend]}/en/**/*").select { |path| File.file?(path) }
88
+ @_frontend_translations = { en: {} }
89
+
90
+ all_files.each do |path|
91
+ lang_key = path.gsub("#{options[:frontend]}/en/", "").gsub(".json", "")
92
+ @_frontend_translations[:en][lang_key] = load_json(path)
93
+ end
94
+
95
+ @_frontend_translations
96
+ end
97
+
98
+ def load_json(file_path)
99
+ return {} unless File.file?(file_path)
100
+
101
+ JSON.parse(File.read(file_path, encoding: "utf-8"))
102
+ end
103
+
104
+ def flatten_hash(hash, prefix = nil)
105
+ hash.each_with_object({}) do |(key, value), result|
106
+ current_key = prefix ? "#{prefix}.#{key}" : key.to_s
107
+ if value.is_a?(Hash)
108
+ result.merge!(flatten_hash(value, current_key))
109
+ else
110
+ result[current_key] = value
111
+ end
112
+ end
113
+ end
114
+
115
+ def flatten_hash_with_colon(hash)
116
+ hash.flat_map do |file_key, file_content|
117
+ flatten_hash(file_content).map do |translation_key, translation_value|
118
+ ["#{file_key}:#{translation_key}", translation_value]
119
+ end
120
+ end.to_h
121
+ end
122
+ end
123
+ end
124
+ end
@@ -18,7 +18,8 @@ module NeetoTranslateCli
18
18
  metadata: {
19
19
  repo: options[:repo],
20
20
  frontend: options[:frontend],
21
- backend: options[:backend]
21
+ backend: options[:backend],
22
+ branch: options[:branch]
22
23
  }
23
24
  }
24
25
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "api"
4
4
  require_relative "payload_builder"
5
+ require_relative "next_i18next/payload_builder"
5
6
 
6
7
  module NeetoTranslateCli
7
8
  class Translator
@@ -19,7 +20,9 @@ module NeetoTranslateCli
19
20
  private
20
21
 
21
22
  def translate!
22
- payload_builder = PayloadBuilder.new(options)
23
+ payload_builder = options[:strategy] == "next-i18next" ?
24
+ NeetoTranslateCli::NextI18next::PayloadBuilder.new(options)
25
+ : PayloadBuilder.new(options)
23
26
  payload = payload_builder.process!
24
27
 
25
28
  if payload_builder.no_new_changes?(payload)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NeetoTranslateCli
4
- VERSION = "0.1.8"
4
+ VERSION = "0.2.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neeto-translate-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abhay V Ashokan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-08-04 00:00:00.000000000 Z
11
+ date: 2025-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -40,6 +40,7 @@ files:
40
40
  - exe/neeto-translate-cli
41
41
  - lib/neeto_translate_cli/api.rb
42
42
  - lib/neeto_translate_cli/cli.rb
43
+ - lib/neeto_translate_cli/next_i18next/payload_builder.rb
43
44
  - lib/neeto_translate_cli/payload_builder.rb
44
45
  - lib/neeto_translate_cli/translator.rb
45
46
  - lib/neeto_translate_cli/version.rb