canvas-i18n-editor 0.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 +7 -0
- data/bin/canvas-i18n-editor +164 -0
- 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: []
|