sync-strings 0.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 +7 -0
- data/bin/sync-strings +67 -0
- data/lib/sync-strings.rb +130 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 173b46f90fc054e72d5c6232cf60e6c64cf8fa8f1f5b060ca6597eccc08268ca
|
4
|
+
data.tar.gz: 337b2fcd5fe8d8a0f75ef61c712d15dcb7d202455c87165ab0bdb9d9c0bb90ff
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3e37f09832ecbc46081bba33532e880498b4afa6060327459954747c9fa27772406f36054df76916f31b3a8eb04e4c195b11f484f3b107e72ecae7a720293acd
|
7
|
+
data.tar.gz: d667b9ccb9b2ec15ba22990330d460a2f9bd000937b2deb4bec6302603d942d210672c021ea600669083610e94d0bfe4ab86f4b3566c19e565d23ead0c263039
|
data/bin/sync-strings
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'sync-strings'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
@options = {}
|
7
|
+
|
8
|
+
option_parser = OptionParser.new do |parser|
|
9
|
+
parser.banner = "Usage: sync-string [paths]"
|
10
|
+
parser.on("-c", "--copy-mismatched-keys-as-values", "Copy Mismatched keys as values") do
|
11
|
+
@options[:copy_mismatched_keys_as_values] = true
|
12
|
+
end
|
13
|
+
parser.on("-s", "--scan[=PATH]", "Recursively scan for localization files relative to the current working directory") do |path|
|
14
|
+
@options[:scan] = true
|
15
|
+
if !path.nil?
|
16
|
+
@options[:scan_path] = path
|
17
|
+
end
|
18
|
+
end
|
19
|
+
parser.on("--paths x,y,z", Array, "Recursively scan for localization files relative to the current working directory") do |path_list|
|
20
|
+
@options[:path_list] = path_list
|
21
|
+
end
|
22
|
+
parser.on("--ignore x,y,z", Array, "When scanning, ignore paths containing these strings e.g. --ignore \"Pods/\",\"Carthage/\",\".build/\"") do |ignore_list|
|
23
|
+
@options[:ignore_list] = ignore_list
|
24
|
+
end
|
25
|
+
parser.on("-h", "--help", "Print the help menu") do
|
26
|
+
puts parser
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end.parse!
|
30
|
+
|
31
|
+
if @options[:scan]
|
32
|
+
files = StringFileFinder.new.find(@options[:scan_path] || Dir.pwd, @options[:ignore_list])
|
33
|
+
|
34
|
+
files.each { |group|
|
35
|
+
if group.length == 1
|
36
|
+
puts "Warning. Found a localization file with no matching translations #{group[0]}"
|
37
|
+
end
|
38
|
+
}
|
39
|
+
elsif @options[:path_list]
|
40
|
+
files = [@options[:path_list]]
|
41
|
+
else
|
42
|
+
puts "No files to synchronize. Either pass files using --paths=x,y,z or use --scan."
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
46
|
+
puts "Starting synchronization"
|
47
|
+
puts "----------------------"
|
48
|
+
|
49
|
+
for groupIndex in 0 ... files.length do
|
50
|
+
for i in 1 ... files[groupIndex].length do
|
51
|
+
synchronizer = Synchronizer.new(files[groupIndex][i - 1], files[groupIndex][i])
|
52
|
+
|
53
|
+
synchronizer.print_stats
|
54
|
+
|
55
|
+
if @options[:copy_mismatched_keys_as_values]
|
56
|
+
synchronizer.sync()
|
57
|
+
elsif synchronizer.key_differences?
|
58
|
+
raise "Missing translations for keys: #{synchronizer.key_differences}"
|
59
|
+
end
|
60
|
+
|
61
|
+
puts "Done. Writing to file."
|
62
|
+
synchronizer.write()
|
63
|
+
puts "----------------------"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
puts "Done synchronizing #{files.reduce(0) { |acc, curr| acc += curr.length}} files."
|
data/lib/sync-strings.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'apfel'
|
2
|
+
|
3
|
+
class HashStringFileWriter
|
4
|
+
def write(hash, to_filename)
|
5
|
+
file_format = file_format(hash)
|
6
|
+
File.open(to_filename,"w") do |file|
|
7
|
+
file.puts file_format
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def file_format(hash)
|
14
|
+
hash
|
15
|
+
.filter { |key, value|
|
16
|
+
!key.nil? && !key.empty?
|
17
|
+
}
|
18
|
+
.map { |key, value|
|
19
|
+
"\"#{key}\" = \"#{value}\";"
|
20
|
+
}
|
21
|
+
.sort
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Synchronizer
|
26
|
+
def initialize(a_filename, b_filename)
|
27
|
+
@a_filename = a_filename
|
28
|
+
@b_filename = b_filename
|
29
|
+
|
30
|
+
@a_hash = Apfel.parse(@a_filename).to_hash(with_comments: false)
|
31
|
+
@b_hash = Apfel.parse(@b_filename).to_hash(with_comments: false)
|
32
|
+
|
33
|
+
@a_subtract_b = difference(@a_hash, @b_hash)
|
34
|
+
@b_subtract_a = difference(@b_hash, @a_hash)
|
35
|
+
end
|
36
|
+
|
37
|
+
def print_stats()
|
38
|
+
puts "File A: #{@a_filename}"
|
39
|
+
puts "File B: #{@b_filename}"
|
40
|
+
puts "A - B = #{@a_subtract_b.length}"
|
41
|
+
puts "B - A = #{@b_subtract_a.length}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def key_differences()
|
45
|
+
@a_subtract_b + @b_subtract_a
|
46
|
+
end
|
47
|
+
|
48
|
+
def key_differences?()
|
49
|
+
!@a_subtract_b.empty? || !@b_subtract_a.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
def sync()
|
53
|
+
add(@b_subtract_a, @a_hash)
|
54
|
+
add(@a_subtract_b, @b_hash)
|
55
|
+
end
|
56
|
+
|
57
|
+
def write()
|
58
|
+
writer = HashStringFileWriter.new
|
59
|
+
writer.write(@a_hash, @a_filename)
|
60
|
+
writer.write(@b_hash, @b_filename)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def difference(hash, subtracting_hash)
|
66
|
+
keys = hash.keys
|
67
|
+
subtracting_keys = subtracting_hash.keys
|
68
|
+
return keys.difference(subtracting_keys)
|
69
|
+
end
|
70
|
+
|
71
|
+
def add(keys, into_hash)
|
72
|
+
keys.each { |key|
|
73
|
+
into_hash[key] = key
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
require 'find'
|
79
|
+
|
80
|
+
class StringFileFinder
|
81
|
+
def find(dir, ignore_list)
|
82
|
+
paths = []
|
83
|
+
ignore_list = ignore_list || []
|
84
|
+
|
85
|
+
Find.find(dir) do |path|
|
86
|
+
paths << path if path =~ /.*\.strings$/ && ignore_list.none? { |ignore| path.include? ignore }
|
87
|
+
end
|
88
|
+
|
89
|
+
def split_path(path)
|
90
|
+
path.split(File::SEPARATOR).reject(&:empty?)
|
91
|
+
end
|
92
|
+
|
93
|
+
paths_hashed_by_base_path = paths.reduce({}) { |acc, path|
|
94
|
+
base_path = split_path(path)[0...-2].join("/")
|
95
|
+
|
96
|
+
if acc.key?(base_path)
|
97
|
+
acc[base_path].push(path)
|
98
|
+
elsif
|
99
|
+
acc[base_path] = [path]
|
100
|
+
end
|
101
|
+
|
102
|
+
acc
|
103
|
+
}
|
104
|
+
|
105
|
+
paths_by_length_and_name = []
|
106
|
+
paths_hashed_by_base_path.each { |key, same_length_paths|
|
107
|
+
same_name = []
|
108
|
+
same_length_paths.each { |same_length_path|
|
109
|
+
i = same_name.index { |array|
|
110
|
+
array.any? { |v|
|
111
|
+
name = split_path(v).last
|
112
|
+
same_length_path_name = split_path(same_length_path).last
|
113
|
+
name == same_length_path_name
|
114
|
+
}
|
115
|
+
}
|
116
|
+
if i.nil?
|
117
|
+
same_name.push([same_length_path])
|
118
|
+
elsif
|
119
|
+
same_name[i].push(same_length_path)
|
120
|
+
end
|
121
|
+
}
|
122
|
+
|
123
|
+
same_name.each{ |entry|
|
124
|
+
paths_by_length_and_name.push(entry)
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
paths_by_length_and_name
|
129
|
+
end
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sync-strings
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nico Richard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: apfel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.5
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.5
|
27
|
+
description: Adds missing values between .strings files then sorts and filters the
|
28
|
+
result so that line numbers always match between your languages.
|
29
|
+
email: nicorichard@gmail.com
|
30
|
+
executables:
|
31
|
+
- sync-strings
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- bin/sync-strings
|
36
|
+
- lib/sync-strings.rb
|
37
|
+
homepage: https://rubygems.org/gems/sync-strings
|
38
|
+
licenses:
|
39
|
+
- MIT
|
40
|
+
metadata: {}
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubygems_version: 3.1.6
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Synchronize Xcode .strings files
|
60
|
+
test_files: []
|