i18n-magic 0.2.0 → 1.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 +4 -4
- data/.gitignore +5 -0
- data/Gemfile.lock +71 -1
- data/Guardfile +75 -0
- data/README.md +13 -18
- data/dev.sh +30 -0
- data/i18n-magic.gemspec +6 -1
- data/lib/i18n/magic.rb +12 -5
- data/lib/i18n/magic/base_command.rb +15 -0
- data/lib/i18n/magic/commands/add.rb +48 -0
- data/lib/i18n/magic/entity/alphabet.rb +29 -0
- data/lib/i18n/magic/entity/translation_file.rb +79 -0
- data/lib/i18n/magic/entity/translation_record.rb +43 -0
- data/lib/i18n/magic/helpers/environment.rb +12 -0
- data/lib/i18n/magic/helpers/string_ops.rb +60 -0
- data/lib/i18n/magic/version.rb +1 -1
- metadata +69 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de350a396ad7f6f8eff10f7edd1b57d57989afe5
|
4
|
+
data.tar.gz: e3d886339500d887b33f8c9fe8895c4195c8e438
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb3aa4e5ab2058617e4a8d17acecae15ad4b3fb01d5032a161ce72e5cf04a6a40835ee55ced670528fd85c4b6b48ea790e952ec4e108da1f93c78485f63d0fd3
|
7
|
+
data.tar.gz: 52d85e60d58ea38dac54c1ac7d74646f47479170fca048ae0bbb03baff87ff3a22cfe3de41044aa0c6d5473fe68cca0a15a63f567480f4f983c1f587a3c72019
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,65 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
i18n-magic (
|
4
|
+
i18n-magic (1.0.0)
|
5
|
+
activesupport
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
10
|
+
activesupport (5.1.5)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (~> 0.7)
|
13
|
+
minitest (~> 5.1)
|
14
|
+
tzinfo (~> 1.1)
|
15
|
+
ast (2.4.0)
|
16
|
+
coderay (1.1.2)
|
17
|
+
concurrent-ruby (1.0.5)
|
9
18
|
diff-lcs (1.3)
|
19
|
+
ffi (1.9.23)
|
20
|
+
formatador (0.2.5)
|
21
|
+
guard (2.14.2)
|
22
|
+
formatador (>= 0.2.4)
|
23
|
+
listen (>= 2.7, < 4.0)
|
24
|
+
lumberjack (>= 1.0.12, < 2.0)
|
25
|
+
nenv (~> 0.1)
|
26
|
+
notiffany (~> 0.0)
|
27
|
+
pry (>= 0.9.12)
|
28
|
+
shellany (~> 0.0)
|
29
|
+
thor (>= 0.18.1)
|
30
|
+
guard-compat (1.2.1)
|
31
|
+
guard-rspec (4.7.3)
|
32
|
+
guard (~> 2.1)
|
33
|
+
guard-compat (~> 1.1)
|
34
|
+
rspec (>= 2.99.0, < 4.0)
|
35
|
+
guard-rubocop (1.3.0)
|
36
|
+
guard (~> 2.0)
|
37
|
+
rubocop (~> 0.20)
|
38
|
+
i18n (0.9.5)
|
39
|
+
concurrent-ruby (~> 1.0)
|
40
|
+
listen (3.1.5)
|
41
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
42
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
43
|
+
ruby_dep (~> 1.2)
|
44
|
+
lumberjack (1.0.12)
|
45
|
+
method_source (0.9.0)
|
46
|
+
minitest (5.11.3)
|
47
|
+
nenv (0.3.0)
|
48
|
+
notiffany (0.1.1)
|
49
|
+
nenv (~> 0.1)
|
50
|
+
shellany (~> 0.0)
|
51
|
+
parallel (1.12.1)
|
52
|
+
parser (2.5.0.4)
|
53
|
+
ast (~> 2.4.0)
|
54
|
+
powerpack (0.1.1)
|
55
|
+
pry (0.11.3)
|
56
|
+
coderay (~> 1.1.0)
|
57
|
+
method_source (~> 0.9.0)
|
58
|
+
rainbow (3.0.0)
|
10
59
|
rake (10.5.0)
|
60
|
+
rb-fsevent (0.10.3)
|
61
|
+
rb-inotify (0.9.10)
|
62
|
+
ffi (>= 0.5.0, < 2)
|
11
63
|
rspec (3.7.0)
|
12
64
|
rspec-core (~> 3.7.0)
|
13
65
|
rspec-expectations (~> 3.7.0)
|
@@ -21,12 +73,30 @@ GEM
|
|
21
73
|
diff-lcs (>= 1.2.0, < 2.0)
|
22
74
|
rspec-support (~> 3.7.0)
|
23
75
|
rspec-support (3.7.0)
|
76
|
+
rubocop (0.53.0)
|
77
|
+
parallel (~> 1.10)
|
78
|
+
parser (>= 2.5)
|
79
|
+
powerpack (~> 0.1)
|
80
|
+
rainbow (>= 2.2.2, < 4.0)
|
81
|
+
ruby-progressbar (~> 1.7)
|
82
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
83
|
+
ruby-progressbar (1.9.0)
|
84
|
+
ruby_dep (1.5.0)
|
85
|
+
shellany (0.0.1)
|
86
|
+
thor (0.20.0)
|
87
|
+
thread_safe (0.3.6)
|
88
|
+
tzinfo (1.2.5)
|
89
|
+
thread_safe (~> 0.1)
|
90
|
+
unicode-display_width (1.3.0)
|
24
91
|
|
25
92
|
PLATFORMS
|
26
93
|
ruby
|
27
94
|
|
28
95
|
DEPENDENCIES
|
29
96
|
bundler (~> 1.16)
|
97
|
+
guard
|
98
|
+
guard-rspec
|
99
|
+
guard-rubocop
|
30
100
|
i18n-magic!
|
31
101
|
rake (~> 10.0)
|
32
102
|
rspec (~> 3.0)
|
data/Guardfile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
19
|
+
# rspec may be run, below are examples of the most common uses.
|
20
|
+
# * bundler: 'bundle exec rspec'
|
21
|
+
# * bundler binstubs: 'bin/rspec'
|
22
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
23
|
+
# installed the spring binstubs per the docs)
|
24
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
+
# * 'just' rspec: 'rspec'
|
26
|
+
|
27
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
28
|
+
require "guard/rspec/dsl"
|
29
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
30
|
+
|
31
|
+
# Feel free to open issues for suggestions and improvements
|
32
|
+
|
33
|
+
# RSpec files
|
34
|
+
rspec = dsl.rspec
|
35
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
36
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
37
|
+
watch(rspec.spec_files)
|
38
|
+
|
39
|
+
# Ruby files
|
40
|
+
ruby = dsl.ruby
|
41
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
42
|
+
|
43
|
+
# Rails files
|
44
|
+
rails = dsl.rails(view_extensions: %w(erb haml slim))
|
45
|
+
dsl.watch_spec_files_for(rails.app_files)
|
46
|
+
dsl.watch_spec_files_for(rails.views)
|
47
|
+
|
48
|
+
watch(rails.controllers) do |m|
|
49
|
+
[
|
50
|
+
rspec.spec.call("routing/#{m[1]}_routing"),
|
51
|
+
rspec.spec.call("controllers/#{m[1]}_controller"),
|
52
|
+
rspec.spec.call("acceptance/#{m[1]}")
|
53
|
+
]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Rails config changes
|
57
|
+
watch(rails.spec_helper) { rspec.spec_dir }
|
58
|
+
watch(rails.routes) { "#{rspec.spec_dir}/routing" }
|
59
|
+
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
|
60
|
+
|
61
|
+
# Capybara features specs
|
62
|
+
watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
|
63
|
+
watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
|
64
|
+
|
65
|
+
# Turnip features and steps
|
66
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
67
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
68
|
+
Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
guard :rubocop do
|
73
|
+
watch(%r{.+\.rb$})
|
74
|
+
watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
|
75
|
+
end
|
data/README.md
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
# I18n::Magic
|
2
2
|
|
3
|
-
|
3
|
+
[](https://codeclimate.com/github/a-smadi/i18n-magic/maintainability)
|
4
|
+
[](https://travis-ci.org/a-smadi/i18n-magic)
|
4
5
|
|
5
|
-
|
6
|
+
Easy localization management for Ruby projects that are using the i18n gem.
|
6
7
|
|
7
|
-
##
|
8
|
+
## Features
|
9
|
+
|
10
|
+
* add translation key and values from the command line
|
11
|
+
* add missing translations using a HTTP web form
|
12
|
+
* format existing localization files
|
8
13
|
|
9
|
-
|
14
|
+
## Installation
|
10
15
|
|
11
16
|
```ruby
|
12
17
|
gem 'i18n-magic'
|
@@ -20,24 +25,14 @@ Or install it yourself as:
|
|
20
25
|
|
21
26
|
$ gem install i18n-magic
|
22
27
|
|
23
|
-
##
|
24
|
-
|
25
|
-
TODO: Write usage instructions here
|
28
|
+
## Tests
|
26
29
|
|
27
|
-
|
30
|
+
You can run tests using `rake` or `rake spec`
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
-
|
33
|
-
## Contributing
|
32
|
+
## Usage
|
34
33
|
|
35
|
-
|
34
|
+
This section will be updated as features roll out.
|
36
35
|
|
37
36
|
## License
|
38
37
|
|
39
38
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
40
|
-
|
41
|
-
## Code of Conduct
|
42
|
-
|
43
|
-
Everyone interacting in the I18n::Magic project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/i18n-magic/blob/master/CODE_OF_CONDUCT.md).
|
data/dev.sh
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e # Exit on errors
|
4
|
+
|
5
|
+
if [ -n "$TMUX" ]; then
|
6
|
+
export NESTED_TMUX=1
|
7
|
+
export TMUX=''
|
8
|
+
fi
|
9
|
+
|
10
|
+
if [ ! $I18N_MAGIC_DIR ]; then export I18N_MAGIC_DIR=$HOME/workspace/i18n-magic; fi
|
11
|
+
|
12
|
+
cd $I18N_MAGIC_DIR
|
13
|
+
|
14
|
+
tmux new-session -d -s i18n-magic
|
15
|
+
tmux set-environment -t i18n-magic -g I18N_MAGIC_DIR $I18N_MAGIC_DIR
|
16
|
+
|
17
|
+
tmux new-window -t i18n-magic -n 'guard'
|
18
|
+
tmux send-key -t i18n-magic 'cd $I18N_MAGIC_DIR' Enter 'bundle exec guard' Enter
|
19
|
+
|
20
|
+
tmux new-window -t i18n-magic -n 'console'
|
21
|
+
tmux send-key -t i18n-magic 'cd $I18N_MAGIC_DIR' Enter 'bundle console' Enter
|
22
|
+
|
23
|
+
tmux new-window -t i18n-magic -n 'vim'
|
24
|
+
tmux send-key -t i18n-magic 'cd $I18N_MAGIC_DIR' Enter 'vim .' Enter
|
25
|
+
|
26
|
+
if [ -z "$NESTED_TMUX" ]; then
|
27
|
+
tmux -2 attach-session -t i18n-magic
|
28
|
+
else
|
29
|
+
tmux -2 switch-client -t i18n-magic
|
30
|
+
fi
|
data/i18n-magic.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["alielsmadi@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{a gem to better manage i18n translation files.}
|
13
|
-
spec.description = %q{easy localization management for Ruby projects using the i18n gem.}
|
13
|
+
spec.description = %q{easy localization management for Ruby projects that are using the i18n gem.}
|
14
14
|
spec.homepage = "https://github.com/a-smadi/i18n-magic"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -33,4 +33,9 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency "bundler", "~> 1.16"
|
34
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
35
35
|
spec.add_development_dependency "rspec", "~> 3.0"
|
36
|
+
spec.add_development_dependency "guard"
|
37
|
+
spec.add_development_dependency "guard-rspec"
|
38
|
+
spec.add_development_dependency "guard-rubocop"
|
39
|
+
|
40
|
+
spec.add_dependency "activesupport"
|
36
41
|
end
|
data/lib/i18n/magic.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
2
3
|
require 'optparse'
|
3
4
|
|
5
|
+
require_relative 'magic/commands/add'
|
6
|
+
require_relative 'magic/version'
|
7
|
+
|
4
8
|
module I18n
|
5
9
|
module Magic
|
6
10
|
class CommandHandler
|
11
|
+
UNDER_DEV_MSG = 'This feature is under development..'.freeze
|
12
|
+
|
7
13
|
def initialize(args)
|
14
|
+
@args = args
|
8
15
|
@opt_parser = OptionParser.new do |opt|
|
9
16
|
opt.banner = 'Usage:'
|
10
17
|
opt.separator ' i18n-magic [command] [options]'
|
@@ -56,19 +63,19 @@ module I18n
|
|
56
63
|
end
|
57
64
|
|
58
65
|
def add
|
59
|
-
|
66
|
+
I18n::Magic::Commands::Add.new(key: @args[1], values: @args[2..-1]).execute
|
60
67
|
end
|
61
68
|
|
62
69
|
def server
|
63
|
-
puts
|
70
|
+
puts UNDER_DEV_MSG
|
64
71
|
end
|
65
72
|
|
66
73
|
def format
|
67
|
-
puts
|
74
|
+
puts UNDER_DEV_MSG
|
68
75
|
end
|
69
76
|
|
70
77
|
def config
|
71
|
-
puts
|
78
|
+
puts UNDER_DEV_MSG
|
72
79
|
end
|
73
80
|
end
|
74
81
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../base_command'
|
2
|
+
require_relative '../entity/translation_file'
|
3
|
+
require_relative '../entity/translation_record'
|
4
|
+
require_relative '../helpers/environment'
|
5
|
+
require_relative '../helpers/string_ops'
|
6
|
+
|
7
|
+
module I18n
|
8
|
+
module Magic
|
9
|
+
module Commands
|
10
|
+
class Add < I18n::Magic::BaseCommand
|
11
|
+
def execute
|
12
|
+
abort('missing key operand') unless @options[:key].present?
|
13
|
+
if @options[:values].size.positive?
|
14
|
+
add_values_from_args
|
15
|
+
else
|
16
|
+
add_values_from_input
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def add_values_from_input
|
23
|
+
I18n::Magic::Helpers::Environment.locales.each do |locale|
|
24
|
+
print "#{locale} for #{@options[:key]} (empty to add skip) : "
|
25
|
+
value = STDIN.gets
|
26
|
+
record = I18n::Magic::Entity::TranslationRecord.new(@options[:key], value)
|
27
|
+
next unless record.valid?
|
28
|
+
translation_file = I18n::Magic::Entity::TranslationFile.new(locale)
|
29
|
+
abort('translation file does not exist !') unless translation_file.exists?
|
30
|
+
translation_file.add(record)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_values_from_args
|
35
|
+
@options[:values].each do |value|
|
36
|
+
next unless value.present?
|
37
|
+
record = I18n::Magic::Entity::TranslationRecord.new(@options[:key], value)
|
38
|
+
abort('invalid key,value pair !') unless record.valid?
|
39
|
+
locale = I18n::Magic::Helpers::StringOps.locale(value)
|
40
|
+
translation_file = I18n::Magic::Entity::TranslationFile.new(locale)
|
41
|
+
abort('translation file does not exist !') unless translation_file.exists?
|
42
|
+
translation_file.add(record)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../helpers/string_ops'
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Magic
|
5
|
+
module Entity
|
6
|
+
class Alphabet
|
7
|
+
attr_reader :letters
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@letters = %w[]
|
11
|
+
end
|
12
|
+
|
13
|
+
def learn(sample_text)
|
14
|
+
return unless sample_text.present? && sample_text.size.positive?
|
15
|
+
normalized_text = I18n::Magic::Helpers::StringOps.letters_only(sample_text).downcase
|
16
|
+
normalized_text.chars.each { |character| @letters.push(character) unless @letters.include?(character) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def belonging_score(text)
|
20
|
+
score = 0
|
21
|
+
normalized_text = I18n::Magic::Helpers::StringOps.letters_only(text).downcase
|
22
|
+
return 0 unless normalized_text.present? && normalized_text.size.positive?
|
23
|
+
normalized_text.chars.each { |character| score += (100.0 / normalized_text.size) if @letters.include?(character) }
|
24
|
+
score.to_i
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative '../helpers/string_ops'
|
2
|
+
require_relative 'translation_record'
|
3
|
+
require_relative 'alphabet'
|
4
|
+
|
5
|
+
module I18n
|
6
|
+
module Magic
|
7
|
+
module Entity
|
8
|
+
class TranslationFile
|
9
|
+
def initialize(locale)
|
10
|
+
@locale = locale
|
11
|
+
@filename = "config/locales/#{locale.downcase}.yml"
|
12
|
+
end
|
13
|
+
|
14
|
+
def exists?
|
15
|
+
File.file?(@filename)
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(record)
|
19
|
+
open(@filename, 'r+') do |file|
|
20
|
+
if find(" #{record.key}:").positive?
|
21
|
+
puts "this key already exists for :#{@locale}"
|
22
|
+
break
|
23
|
+
end
|
24
|
+
position = find("# #{record.key.slice(0).upcase} #") + 1
|
25
|
+
abort('translation file is not properly formatted !') unless position.positive?
|
26
|
+
position.times { file.readline }
|
27
|
+
prev = file.pos
|
28
|
+
current_key = file.readline
|
29
|
+
pos = file.pos
|
30
|
+
while skip_this_line?(record.key, current_key.strip)
|
31
|
+
prev = pos
|
32
|
+
current_key = file.readline
|
33
|
+
pos = file.pos
|
34
|
+
end
|
35
|
+
file.seek(prev)
|
36
|
+
remainder = file.read
|
37
|
+
file.seek(prev)
|
38
|
+
file.write("#{record.as_string_row}\n" + remainder)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def compatibility_score(text)
|
43
|
+
locale_alphabet = I18n::Magic::Entity::Alphabet.new
|
44
|
+
open(@filename, 'r+') do |file|
|
45
|
+
%w[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z].each do |letter|
|
46
|
+
file.seek(0)
|
47
|
+
position = find("# #{letter} #") + 1
|
48
|
+
abort('translation file is not properly formatted !') unless position.positive?
|
49
|
+
position.times { file.readline }
|
50
|
+
sample_text = file.readline
|
51
|
+
next unless sample_text.present? && sample_text.include?(':')
|
52
|
+
sample_text = sample_text[(sample_text.index(':') + 1)..-1].strip
|
53
|
+
locale_alphabet.learn(sample_text)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
locale_alphabet.belonging_score(text)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def find(keyword)
|
62
|
+
count = 0
|
63
|
+
File.open(@filename, 'r') do |file|
|
64
|
+
file.each_line do |line|
|
65
|
+
count += 1
|
66
|
+
return count if line.match?(/#{keyword}/)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
-1
|
70
|
+
end
|
71
|
+
|
72
|
+
def skip_this_line?(key, current_key)
|
73
|
+
return false if current_key.start_with?('#')
|
74
|
+
key == [key, current_key.downcase].sort_by! { |text| text }.last
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../helpers/string_ops'
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Magic
|
5
|
+
module Entity
|
6
|
+
class TranslationRecord
|
7
|
+
attr_reader :key, :value
|
8
|
+
|
9
|
+
def initialize(key, value)
|
10
|
+
@key = key
|
11
|
+
@value = value
|
12
|
+
clean
|
13
|
+
prepare_key
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid?
|
17
|
+
@key.present? && @value.present? && !@key.empty? && !@value.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def as_string_row
|
21
|
+
" #{@key}: #{@value}"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def clean
|
27
|
+
@key = @key.to_s.strip
|
28
|
+
@value = @value.to_s.strip
|
29
|
+
@value = "'#{@value}'" if !@value.start_with?('\'') && value_has_variable?
|
30
|
+
end
|
31
|
+
|
32
|
+
def prepare_key
|
33
|
+
@key = (@key[1..-1]).strip if @key.start_with?(':')
|
34
|
+
@key = I18n::Magic::Helpers::StringOps.underscore(@key)
|
35
|
+
end
|
36
|
+
|
37
|
+
def value_has_variable?
|
38
|
+
@value.include?('%{') && (@value.index('}', @value.index('%{')) || -1).positive?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module I18n
|
2
|
+
module Magic
|
3
|
+
module Helpers
|
4
|
+
class Environment
|
5
|
+
def self.locales
|
6
|
+
locale_files = Dir['config/locales/*.yml'].select { |f| f =~ %r/\/[a-z]{2}.yml/ }
|
7
|
+
locale_files.map { |f| f.remove('config/locales/').remove('.yml').upcase }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative 'environment'
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Magic
|
5
|
+
module Helpers
|
6
|
+
class StringOps
|
7
|
+
def self.underscore(text)
|
8
|
+
text.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.locale(text)
|
12
|
+
locales = I18n::Magic::Helpers::Environment.locales
|
13
|
+
text_locale = locales[0]
|
14
|
+
score = 0
|
15
|
+
locales.each do |locale|
|
16
|
+
locale_score = I18n::Magic::Entity::TranslationFile.new(locale).compatibility_score(text)
|
17
|
+
if locale_score > score
|
18
|
+
text_locale = locale
|
19
|
+
score = locale_score
|
20
|
+
end
|
21
|
+
end
|
22
|
+
text_locale
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.letters_only(text)
|
26
|
+
text.tr('0-9', '')
|
27
|
+
.tr('!', '')
|
28
|
+
.tr('?', '')
|
29
|
+
.tr('@', '')
|
30
|
+
.tr('#', '')
|
31
|
+
.tr('$', '')
|
32
|
+
.tr('%', '')
|
33
|
+
.tr('^', '')
|
34
|
+
.tr('&', '')
|
35
|
+
.tr('*', '')
|
36
|
+
.tr('(', '')
|
37
|
+
.tr(')', '')
|
38
|
+
.tr('[', '')
|
39
|
+
.tr(']', '')
|
40
|
+
.tr('{', '')
|
41
|
+
.tr('}', '')
|
42
|
+
.tr(':', '')
|
43
|
+
.tr(';', '')
|
44
|
+
.tr('\'', '')
|
45
|
+
.tr('"', '')
|
46
|
+
.tr('`', '')
|
47
|
+
.tr('\\', '')
|
48
|
+
.tr('/', '')
|
49
|
+
.tr('<', '')
|
50
|
+
.tr('>', '')
|
51
|
+
.tr('.', '')
|
52
|
+
.tr(',', '')
|
53
|
+
.tr('|', '')
|
54
|
+
.tr(' ', '')
|
55
|
+
.strip.downcase
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/i18n/magic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-magic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ali Smadi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,7 +52,64 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
-
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activesupport
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: easy localization management for Ruby projects that are using the i18n
|
112
|
+
gem.
|
56
113
|
email:
|
57
114
|
- alielsmadi@gmail.com
|
58
115
|
executables:
|
@@ -66,14 +123,23 @@ files:
|
|
66
123
|
- CODE_OF_CONDUCT.md
|
67
124
|
- Gemfile
|
68
125
|
- Gemfile.lock
|
126
|
+
- Guardfile
|
69
127
|
- LICENSE.txt
|
70
128
|
- README.md
|
71
129
|
- Rakefile
|
72
130
|
- bin/console
|
73
131
|
- bin/setup
|
132
|
+
- dev.sh
|
74
133
|
- exe/i18n-magic
|
75
134
|
- i18n-magic.gemspec
|
76
135
|
- lib/i18n/magic.rb
|
136
|
+
- lib/i18n/magic/base_command.rb
|
137
|
+
- lib/i18n/magic/commands/add.rb
|
138
|
+
- lib/i18n/magic/entity/alphabet.rb
|
139
|
+
- lib/i18n/magic/entity/translation_file.rb
|
140
|
+
- lib/i18n/magic/entity/translation_record.rb
|
141
|
+
- lib/i18n/magic/helpers/environment.rb
|
142
|
+
- lib/i18n/magic/helpers/string_ops.rb
|
77
143
|
- lib/i18n/magic/version.rb
|
78
144
|
homepage: https://github.com/a-smadi/i18n-magic
|
79
145
|
licenses:
|