canvas-i18n-editor 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/bin/canvas-i18n-editor +164 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '0777905a738e9fee9146ed71fef0f70fad8018df1f834e425cd9348bc7aa98f4'
4
+ data.tar.gz: da069aed8d20995f8bc51a464ea78a58a9873d93a3547a06eec987b199c8e5d0
5
+ SHA512:
6
+ metadata.gz: ad3f83a7151abebeff87dd96232ff801374ecd11578ecd51de02835094284dd52c6ec1e28e0c1e4cf3964b34933ec987710f3b3ae3bd7651610580c4e5636a0b
7
+ data.tar.gz: ef6feaee7ba8125d6a443374a9262b129980a15c8e7837848a9e9a16c17e1f0924364553f888898b4071c346a3a5419dd9e2ec758952b763c71ff47708f0fe42
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "zlib"
5
+ require "optparse"
6
+ require "fileutils"
7
+ require "json"
8
+
9
+ Options = Struct.new(:translate_from, :translate_to, :mode, :apply_js)
10
+
11
+ ACCEPTED_MODE = %w[canvas rails reverse].freeze
12
+
13
+ LOCALE_FILE = "config/locales/zh-Hant.yml"
14
+ JS_LOCALE_FILE = "public/javascripts/translations/zh-Hant.json"
15
+ TMP_FILE = "/tmp/canvas-i18n"
16
+
17
+ # index = 4, skip 4 lines to translation body
18
+ def update_rails_i18n(args)
19
+ raw_key = args.translate_from
20
+ # find key in config/locales/zh-Hant.yml
21
+ data = File.readlines(LOCALE_FILE)
22
+ keywords = raw_key.split(".")
23
+ current_layer = 1
24
+ get_layer = -> { _1.match(/^\s*/)[0].size / 2 }
25
+ updated_flag = false
26
+ File.open(TMP_FILE, "w:UTF-8") do |file|
27
+ data[0..3].each { file.write(_1) }
28
+ (4..data.size - 1).each do |line_index|
29
+ line = data[line_index]
30
+ unless updated_flag
31
+ if data[line_index].match?(/^\s*#{keywords[0]}:/)
32
+ line_number = line_index + 1
33
+ key = keywords.shift
34
+ current_layer += 1
35
+ puts "find #{key} in line #{line_number}"
36
+ # find last key, should update content now
37
+ if keywords.empty?
38
+ line = line.sub(/#{key}:\s?/, "#{key}: ").sub(/(?<=#{key}:\s).+/, "\"#{args.translate_to}\"")
39
+ updated_flag = true
40
+ end
41
+ elsif line_index < data.size - 1 && get_layer[data[line_index + 1]] < current_layer
42
+ # determine can't find key early, update with nested structure
43
+ update_nested_key(file, keywords, current_layer, args)
44
+ updated_flag = true
45
+ end
46
+ end
47
+
48
+ file.write(line)
49
+ end
50
+
51
+ update_nested_key(file, keywords, current_layer, args) unless updated_flag
52
+ file.close
53
+ end
54
+ FileUtils.mv(TMP_FILE, LOCALE_FILE)
55
+ update_js(raw_key, args.translate_to, args.apply_js)
56
+ end
57
+
58
+ def update_nested_key(file, keywords, current_layer, args)
59
+ keywords[0..-2].each do |key|
60
+ file.write("#{' ' * 2 * current_layer}#{key}: \n")
61
+ current_layer += 1
62
+ end
63
+ file.write("#{' ' * 2 * current_layer}#{keywords[-1]}: #{args.translate_to}\n")
64
+ end
65
+
66
+ def update_js(key, translate_to, apply_js)
67
+ data = File.read(JS_LOCALE_FILE)
68
+ data = data.sub(/(?<="#{key}":)"[^"]+"/, "\"#{translate_to}\"")
69
+ puts "update js translations"
70
+
71
+ File.write(JS_LOCALE_FILE, data)
72
+ generate_hashed_js if apply_js
73
+ end
74
+
75
+ def generate_hashed_js
76
+ `rm public/dist/javascripts/translations/zh-Hant-*.json`
77
+ puts "generate scoped js translations"
78
+ `bundle exec rails js:gulp_rev`
79
+ end
80
+
81
+ def update_canvas_i18n(args)
82
+ hash = Zlib.crc32("#{args.translate_from.size}:#{args.translate_from}").to_s(16)
83
+ prefix = args.translate_from.downcase[0,50].gsub(/[\s\-\/_:]{1,}/, "_").gsub(/[^a-zA-Z0-9_-]/, "")
84
+ key = "#{prefix}_#{hash}"
85
+ updated_flag = false
86
+ # find key in config/locales/zh-Hant.yml
87
+ File.open(TMP_FILE, "w:UTF-8") do |file|
88
+ File.readlines(LOCALE_FILE).each_with_index do |line, line_index|
89
+ if !updated_flag && line.match?(/^\s*#{key}:/)
90
+ line_number = line_index + 1
91
+ puts "find key in line #{line_number}"
92
+ line = line.sub(/#{key}:\s?/, "#{key}: ").sub(/(?<=#{key}:\s).+/, "\"#{args.translate_to}\"")
93
+ updated_flag = true
94
+ end
95
+
96
+ file.write(line)
97
+ end
98
+
99
+ unless updated_flag
100
+ puts "specified key not found in locale file, create one in last line"
101
+ file.write(" #{key}: #{args.translate_to}\n")
102
+ end
103
+
104
+ file.close
105
+ end
106
+
107
+ FileUtils.mv(TMP_FILE, LOCALE_FILE)
108
+ update_js(key, args.translate_to, args.apply_js)
109
+ end
110
+
111
+ def update_from_content(args)
112
+ search_keyword = args.translate_from
113
+ # TODO: use translate_from(means original content here) to search for key(query like %keyword%)
114
+ # TODO: raise error if there's multiple candidate
115
+ # TODO: use the key to update yml directly, and get full key if it's rails i18n
116
+ # TODO: use key(full key) to update_js
117
+ end
118
+
119
+ class Parser
120
+ def self.parse(user_input)
121
+ args = Options.new
122
+
123
+ opt_parser = OptionParser.new do |opts|
124
+ opts.banner = "Usage:
125
+ cool_i18n_edit translateFrom translateTo [options]
126
+
127
+ cool_i18n_edit -t canvas 'Click Me' '點我' # edit i18n using canvas liner-style key
128
+ cool_i18n_edit -t rails 'controller_name.action_name.click_me' '點我' # edit i18n using rails i18n key
129
+ "
130
+
131
+ opts.on("-m MODE", "--mode MODE", "canvas, rails or reverse") do |mode|
132
+ args.mode = mode
133
+ end
134
+
135
+ opts.on("-a", "--apply", "apply js translations") do
136
+ args.apply_js = true
137
+ end
138
+
139
+ opts.on("-h", "--help", "Prints this help") do
140
+ puts opts
141
+ exit
142
+ end
143
+ end
144
+
145
+ opt_parser.parse!(user_input) # options are remove after this line
146
+ raise "-m option not set" unless args.mode
147
+ raise "invalid -m option #{args.mode}\nonly below types are allowed\n#{ACCEPTED_MODE.join(",")}" unless ACCEPTED_MODE.include?(args.mode)
148
+
149
+ args.translate_from = user_input[0].strip
150
+ args.translate_to = user_input[1].strip
151
+
152
+ args
153
+ end
154
+ end
155
+
156
+ args = Parser.parse(ARGV)
157
+ case args.mode
158
+ in "rails"
159
+ update_rails_i18n(args)
160
+ in "canvas"
161
+ update_canvas_i18n(args)
162
+ in "reverse"
163
+ update_from_content(args)
164
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: canvas-i18n-editor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Pero
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-06-28 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: i18n edit
14
+ email: 0711kps@gmail.com
15
+ executables:
16
+ - canvas-i18n-editor
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/canvas-i18n-editor
21
+ homepage: https://rubygems.org/gems/hola
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '2.7'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubygems_version: 3.3.26
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: i18n edit
44
+ test_files: []