loco_tool 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +57 -0
  4. data/bin/locotool +69 -0
  5. data/lib/helper.rb +68 -0
  6. data/lib/logger.rb +68 -0
  7. metadata +114 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 15401c4e789617502cef976d0ade6c0b5ebf4c03e26dda00f5035bca413014e3
4
+ data.tar.gz: f646fa2b23742856f6ee4a9a0506ebfa4d883dc3fc193a16317e3bc02013466e
5
+ SHA512:
6
+ metadata.gz: 1f6249ed214cfa90157f7c8e5454232d6e6965612d6d7770032c9e646884b0486bc983b98b0da2dfd080ce099855be66be83983e7d119cf661cc5ca184a04162
7
+ data.tar.gz: dc8157a6d7b867f3ceab8f6a3a3f294b2fb148bc559017141e9f68e774ad68b9a7fabbc73ad4d085d0749735f05beaff538daa190bbf058dfb25efb1cf0eb726
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Aleksei Cherepanov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # LocoTool
2
+
3
+ LocoTool is a command-line tool for localization tasks, designed to simplify the management and validation of localization strings in iOS and Android projects.
4
+
5
+ ## Features
6
+
7
+ - Find duplicate keys between localization files.
8
+ - Sync and move missing strings between files.
9
+ - Validate and verify localization files.
10
+
11
+ ### TODO
12
+
13
+ - Convert strings between different formats.
14
+
15
+ ## Installation
16
+
17
+ LocoTool can be installed via RubyGems. Make sure you have Ruby installed on your system, then run the following command:
18
+
19
+ ```
20
+ $ gem install loco_tool
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ LocoTool provides various commands to perform localization tasks. Here are some examples:
26
+
27
+ ### Find Duplicate Keys
28
+
29
+ ```
30
+ $ locotool duplicates [FILE_A] [FILE_B]
31
+ ```
32
+
33
+ This command compares two localization files and identifies duplicate keys between them.
34
+
35
+ ### Sync Localization Files
36
+
37
+ ```
38
+ $ locotool sync [PATH_A] [PATH_B] [BASE_LANG] [TARGET_LANG]
39
+ ```
40
+
41
+ This command synchronizes localization files between two directories (`PATH_A` and `PATH_B`). It compares the base language (`BASE_LANG`) with the target language (`TARGET_LANG`) and moves missing strings from the base file to the target file.
42
+
43
+ ### Sync iOS Localization Files Automatically
44
+
45
+ ```
46
+ $ locotool sync_ios_auto [PATH_A] [PATH_B] [BASE_LANG]
47
+ ```
48
+
49
+ This command automatically finds and syncs iOS localization files in the specified directories (`PATH_A` and `PATH_B`). It iterates over the available target languages, excluding the base language (`BASE_LANG`), and performs the synchronization operation.
50
+
51
+ ## Contributing
52
+
53
+ Contributions are welcome! If you have any suggestions, bug reports, or feature requests, please open an issue or submit a pull request on the [LocoTool GitHub repository](https://github.com/ftp27/loco_tool).
54
+
55
+ ## License
56
+
57
+ This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
data/bin/locotool ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "thor"
5
+ require "loco_strings"
6
+ require "./lib/logger"
7
+ require "./lib/helper"
8
+
9
+ # The Locotool class represents a CLI tool for localization tasks.
10
+ #
11
+ # Usage: locotool [command] [options]
12
+ class Locotool < Thor
13
+ desc "dublicates FILE_A FILE_B", "Find duplicate keys in localization files"
14
+ def dublicates(file_a, file_b)
15
+ strings_a = LocoStrings.load(file_a).read
16
+ strings_b = LocoStrings.load(file_b).read
17
+
18
+ strings_a.each do |key, string_a|
19
+ next unless strings_b.key?(key)
20
+
21
+ if string_a.value == strings_b[key].value
22
+ Logger.string(string_a)
23
+ else
24
+ Logger.duplicate(string_a, strings_b[key])
25
+ end
26
+ end
27
+ end
28
+
29
+ desc "sync_ios_auto PATH_A PATH_B BASE_LANG", "Find and sync iOS localization files"
30
+ def sync_ios_auto(path_a, path_b, base_lang)
31
+ target_langs = Helper.find_lproj(path_a)
32
+ target_langs.each do |target_lang|
33
+ next if target_lang == base_lang
34
+
35
+ Logger.header("Language #{Paint[target_lang.to_s, :green]}")
36
+ sync_ios(path_a, path_b, base_lang, target_lang)
37
+ end
38
+ end
39
+
40
+ desc "sync PATH_A PATH_B BASE_LANG TARGET_LANG", "Sync iOS localization files"
41
+ def sync_ios(path_a, path_b, base_lang, target_lang)
42
+ file_a_base = "#{path_a}/#{base_lang}.lproj/Localizable.strings"
43
+ file_a_target = "#{path_a}/#{target_lang}.lproj/Localizable.strings"
44
+ file_b_base = "#{path_b}/#{base_lang}.lproj/Localizable.strings"
45
+ file_b_target = "#{path_b}/#{target_lang}.lproj/Localizable.strings"
46
+ unless File.exist?(file_b_target)
47
+ Logger.file_not_found(file_b_target)
48
+ return
49
+ end
50
+ sync(file_a_base, file_a_target, file_b_base, file_b_target)
51
+ end
52
+
53
+ desc "sync FILE_A_BASE FILE_A_TARGET FILE_B_BASE FILE_B_TARGET", "Sync localization files"
54
+ def sync(file_a_base, file_a_target, file_b_base, file_b_target)
55
+ strings_a_file = LocoStrings.load(file_a_target)
56
+ strings_a_target = strings_a_file.read
57
+ strings_b_file = LocoStrings.load(file_b_target)
58
+ strings_b_file.read
59
+
60
+ lost_keys = Helper.find_missing(file_b_base, file_b_target)
61
+ keys_b_to_a = Helper.make_keys_dict(file_a_base, file_b_base)
62
+ Helper.merge(strings_a_target, strings_b_file, keys_b_to_a, lost_keys)
63
+
64
+ Logger.lost_keys(lost_keys)
65
+ strings_b_file.write
66
+ end
67
+ end
68
+
69
+ Locotool.start(ARGV)
data/lib/helper.rb ADDED
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./lib/logger"
4
+
5
+ # The Helper class provides utility methods for various tasks.
6
+ class Helper
7
+ # Finds lproj localization files in the specified path.
8
+ #
9
+ # @param path [String] The path to search for localization files.
10
+ # @return [Array<String>] An array of language codes found in the path.
11
+ def self.find_lproj(path)
12
+ lproj_files = Dir.glob("#{path}/*.lproj").select { |f| File.directory? f }
13
+ lproj_files.map { |f| File.basename(f, ".lproj") }
14
+ end
15
+
16
+ # Creates a dictionary mapping keys between two localization files.
17
+ #
18
+ # @param base_file [String] The base localization file path.
19
+ # @param target_file [String] The target localization file path.
20
+ # @return [Hash<String, String>] A hash containing key mappings.
21
+ def self.make_keys_dict(base_file, target_file)
22
+ strings_base = LocoStrings.load(base_file).read
23
+ strings_target = LocoStrings.load(target_file).read
24
+ keys = {}
25
+ strings_base.each do |key_base, string_base|
26
+ strings_target.each do |key_target, string_target|
27
+ keys[key_base] = key_target if string_base.value == string_target.value
28
+ end
29
+ end
30
+ keys
31
+ end
32
+
33
+ # Finds missing keys in the target localization file compared to the base file.
34
+ #
35
+ # @param file_a [String] The base localization file path.
36
+ # @param file_b [String] The target localization file path.
37
+ # @return [Array<String>] An array of missing keys in the target file.
38
+ def self.find_missing(file_a, file_b)
39
+ strings_a = LocoStrings.load(file_a).read
40
+ strings_b = LocoStrings.load(file_b).read
41
+
42
+ lost_keys = []
43
+ strings_a.each do |key, _string_a|
44
+ lost_keys << key unless strings_b.key?(key)
45
+ end
46
+ lost_keys
47
+ end
48
+
49
+ # Merges the source strings into the target strings
50
+ #
51
+ # @param source [Hash] The source strings hash
52
+ # @param _target [Hash] The target strings hash (not used in this method)
53
+ # @param keys [Hash] A dictionary mapping source keys to target keys
54
+ # @param lost_keys [Array] An array of lost keys to be updated
55
+ #
56
+ # @return [void]
57
+ def self.merge(source, _target, keys, lost_keys)
58
+ source.each do |key, source_string|
59
+ target_key = keys[key]
60
+ next unless target_key
61
+ next unless lost_keys.include?(target_key)
62
+
63
+ strings_b_file.update(target_key, source_string.value)
64
+ lost_keys.delete(target_key)
65
+ Logger.string_value(target_key, source_string.value)
66
+ end
67
+ end
68
+ end
data/lib/logger.rb ADDED
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "paint"
4
+
5
+ # The Logger class provides utility methods for printing console logs with different formatting.
6
+ class Logger
7
+ # Prints a string value.
8
+ #
9
+ # @param string [LocoString] The LocoString object to print.
10
+ def self.string(string)
11
+ puts Formatter.string(string.key, string.value)
12
+ end
13
+
14
+ # Prints a string value.
15
+ #
16
+ # @param key [String] The key of the string.
17
+ # @param value [String] The value of the string.
18
+ def self.string_value(key, value)
19
+ puts Formatter.string(key, value)
20
+ end
21
+
22
+ # Prints a string and its duplicate.
23
+ #
24
+ # @param string [LocoString] The original string.
25
+ # @param duplicate [LocoString] The duplicate string.
26
+ def self.duplicate(string, duplicate)
27
+ puts "#{Formatter.string(string.key, string.value)} ↔ #{Paint[duplicate.value.to_s, :blue]}"
28
+ end
29
+
30
+ # Prints a header.
31
+ #
32
+ # @param text [String] The text to print as the header.
33
+ def self.header(text)
34
+ puts "=" * text.length
35
+ puts text
36
+ puts "=" * text.length
37
+ end
38
+
39
+ # Prints a file not found error message.
40
+ #
41
+ # @param file [String] The file that was not found.
42
+ def self.file_not_found(file)
43
+ puts Paint["#{file} not found", :red]
44
+ end
45
+
46
+ # Prints the lost keys.
47
+ #
48
+ # @param keys [Array<String>] The lost keys to print.
49
+ def self.lost_keys(keys)
50
+ return if keys.empty?
51
+
52
+ puts "Lost keys: #{keys.length}"
53
+ puts keys.map { |key| Paint[key.to_s, :red] }.join(", ")
54
+ end
55
+ end
56
+
57
+ # Provides utility methods for formatting strings
58
+ class Formatter
59
+ # Formats a key-value pair as a string with colored output
60
+ #
61
+ # @param key [String] The key to be formatted
62
+ # @param value [String] The value to be formatted
63
+ #
64
+ # @return [String] The formatted key-value pair as a string
65
+ def self.string(key, value)
66
+ "#{Paint[key, :green]} #{Paint[value, :blue]}"
67
+ end
68
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: loco_tool
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Aleksei Cherepanov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-06-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: loco_strings
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: paint
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.2'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 1.2.2
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '1.2'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.2.2
61
+ - !ruby/object:Gem::Dependency
62
+ name: rubocop
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.52'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.52'
75
+ description: loco_tool is a command-line tool written in Ruby that helps parse, validate,
76
+ and manipulate localization strings for iOS and Android projects.
77
+ email:
78
+ - ftp27host@gmail.com
79
+ executables:
80
+ - locotool
81
+ extensions: []
82
+ extra_rdoc_files:
83
+ - README.md
84
+ - LICENSE
85
+ files:
86
+ - LICENSE
87
+ - README.md
88
+ - bin/locotool
89
+ - lib/helper.rb
90
+ - lib/logger.rb
91
+ homepage: https://github.com/ftp27/loco_tool
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubygems_version: 3.4.13
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: A CLI tool for parsing and validating localization strings
114
+ test_files: []