i18n-tools 0.0.4 → 0.0.5

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.
Files changed (64) hide show
  1. data/lib/core_ext/hash/iterate_nested.rb +35 -0
  2. data/lib/core_ext/hash/slice.rb +20 -0
  3. data/lib/core_ext/hash/sorted_yaml_style.rb +17 -0
  4. data/lib/core_ext/hash/symbolize_keys.rb +14 -0
  5. data/lib/core_ext/module/attribute_accessors.rb +48 -0
  6. data/lib/core_ext/object/deep_clone.rb +5 -0
  7. data/lib/core_ext/object/instance_variables.rb +9 -0
  8. data/lib/core_ext/object/meta_class.rb +5 -0
  9. data/lib/core_ext/object/tap.rb +6 -0
  10. data/lib/i18n/backend/simple_storage.rb +119 -0
  11. data/lib/i18n/commands/keys.rb +84 -0
  12. data/lib/i18n/exceptions/key_exists.rb +9 -0
  13. data/lib/i18n/index.rb +33 -0
  14. data/lib/i18n/index/base.rb +38 -0
  15. data/lib/i18n/index/file.rb +55 -0
  16. data/lib/i18n/index/format.rb +49 -0
  17. data/lib/i18n/index/key.rb +45 -0
  18. data/lib/i18n/index/occurence.rb +18 -0
  19. data/lib/i18n/index/simple.rb +69 -0
  20. data/lib/i18n/index/simple/data.rb +34 -0
  21. data/lib/i18n/index/simple/storage.rb +79 -0
  22. data/lib/i18n/ripper2ruby.rb +7 -0
  23. data/lib/i18n/ripper2ruby/translate_args_list.rb +89 -0
  24. data/lib/i18n/ripper2ruby/translate_call.rb +66 -0
  25. data/lib/i18n/translation_properties.rb +38 -0
  26. data/test/all.rb +1 -1
  27. data/test/core_ext/hash_iterate_nested.rb +31 -0
  28. data/test/fixtures/all.rb.src +106 -0
  29. data/test/fixtures/config.yml +3 -0
  30. data/test/fixtures/locale/de.yml +4 -0
  31. data/test/fixtures/locale/en.yml +4 -0
  32. data/test/fixtures/source_1.rb +2 -1
  33. data/test/fixtures/translate/double_key.rb +32 -0
  34. data/test/fixtures/translate/double_scope.rb +32 -0
  35. data/test/fixtures/translate/single_key.rb +10 -0
  36. data/test/fixtures/translate/single_scope.rb +32 -0
  37. data/test/i18n/backend/simple_storage_test.rb +81 -0
  38. data/test/i18n/backend/translation_properties_test.rb +33 -0
  39. data/test/i18n/index/all.rb +1 -0
  40. data/test/i18n/index/args_replace_test.rb +218 -0
  41. data/test/i18n/index/calls_replace_test.rb +67 -0
  42. data/test/i18n/index/commands_test.rb +75 -0
  43. data/test/i18n/index/key_test.rb +32 -0
  44. data/test/i18n/index/simple_test.rb +67 -0
  45. data/test/i18n/ripper2ruby/translate_call_test.rb +98 -0
  46. data/test/test_helper.rb +66 -9
  47. metadata +49 -32
  48. data/MIT-LICENSE +0 -20
  49. data/README.textile +0 -1
  50. data/bin/i18n-keys +0 -6
  51. data/lib/ansi.rb +0 -19
  52. data/lib/i18n/keys.rb +0 -51
  53. data/lib/i18n/keys/commands.rb +0 -53
  54. data/lib/i18n/keys/formatter.rb +0 -39
  55. data/lib/i18n/keys/index.rb +0 -209
  56. data/lib/i18n/keys/occurence.rb +0 -120
  57. data/lib/i18n/parser/erb_parser.rb +0 -54
  58. data/lib/i18n/parser/ruby_parser.rb +0 -93
  59. data/test/commands_test.rb +0 -1
  60. data/test/erb_parser_test.rb +0 -31
  61. data/test/index_test.rb +0 -135
  62. data/test/keys_test.rb +0 -75
  63. data/test/occurence_test.rb +0 -130
  64. data/test/ruby_parser_test.rb +0 -54
@@ -0,0 +1,98 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ class I18nTranslateCallTest < Test::Unit::TestCase
4
+ include TestRubyBuilderHelper
5
+
6
+ def translate_call(src)
7
+ Ripper::RubyBuilder.new(src).parse.statements.first.to_translate_call
8
+ end
9
+
10
+ def translate_args(src)
11
+ translate_call(src).arguments.tap { |args| class << args; public :key_index; end }
12
+ end
13
+
14
+ define_method :"test: to_translate_call includes TranslateCall to the meta class" do
15
+ call = build('t(:foo)').first
16
+ assert !call.respond_to?(:key)
17
+
18
+ call = call.to_translate_call
19
+ assert call.respond_to?(:key)
20
+ end
21
+
22
+ define_method :"test: to_translate_call includes TranslateArgsList to the arguments' meta class" do
23
+ call = build('t(:foo)').first
24
+ assert !call.arguments.respond_to?(:key)
25
+
26
+ call = call.to_translate_call
27
+ assert call.arguments.respond_to?(:key)
28
+ end
29
+
30
+ def test_collects_all_three_kinds_of_translate_calls
31
+ src = "I18n.t(:foo); t('bar.baz', :scope => [:buz]); t :foo"
32
+ assert_equal 3, build(src).select_translate_calls.size
33
+ end
34
+
35
+ def test_call_to_translate_call
36
+ src = "t(:'bar.baz', :scope => [:foo])"
37
+ call = Ripper::RubyBuilder.new(src).parse.statements.first
38
+ translate_call = call.to_translate_call
39
+
40
+ assert_equal call.target, translate_call.target
41
+ assert_equal call.identifier.token, translate_call.identifier.token
42
+ assert_equal call.to_ruby, translate_call.to_ruby
43
+ assert_equal translate_call, translate_call.arguments.parent
44
+ end
45
+
46
+ def test_translate_call_key
47
+ assert_equal 'bar.baz', translate_call("t('bar.baz', :scope => [:foo])").key
48
+ assert_equal :'bar.baz', translate_call("t(:'bar.baz', :scope => [:foo])").key
49
+ assert_equal [:bar, :baz], translate_call("t([:bar, :baz], :scope => [:foo])").key
50
+ end
51
+
52
+ def test_translate_call_scope
53
+ assert_equal nil, translate_call("t(:bar)").scope
54
+ assert_equal :foo, translate_call("t(:bar, :scope => :foo)").scope
55
+ assert_equal :'foo.bar', translate_call("t(:bar, :scope => :'foo.bar')").scope
56
+ assert_equal [:foo], translate_call("t(:bar, :scope => [:foo])").scope
57
+ end
58
+
59
+ def test_translate_call_full_key
60
+ assert_equal [:bar], translate_call("t(:bar)").full_key
61
+ assert_equal [:foo, :bar], translate_call("t(:bar, :scope => :foo)").full_key
62
+ assert_equal [:foo, :bar, :baz], translate_call("t(:baz, :scope => :'foo.bar')").full_key
63
+ assert_equal [:foo, :bar, :baz], translate_call("t(:baz, :scope => [:foo, :bar])").full_key
64
+ end
65
+
66
+ def test_translate_call_key_matches?
67
+ assert translate_call("t(:foo)").key_matches?(:foo)
68
+
69
+ assert translate_call("t(:'foo.bar')").key_matches?(:foo)
70
+ assert translate_call("t(:'foo.bar')").key_matches?(:'foo.bar')
71
+
72
+ assert translate_call("t(:baz, :scope => [:foo, :bar])").key_matches?(:foo)
73
+ assert translate_call("t(:baz, :scope => [:foo, :bar])").key_matches?(:'foo.bar')
74
+ assert translate_call("t(:baz, :scope => [:foo, :bar])").key_matches?(:'foo.bar.baz')
75
+
76
+ assert !translate_call("t(:foo)").key_matches?(:'bar')
77
+ assert !translate_call("t(:foo)").key_matches?(:'foo.bar')
78
+
79
+ assert !translate_call("t(:'foo.bar')").key_matches?(:'bar.baz')
80
+ assert !translate_call("t(:'foo.bar')").key_matches?(:'foo.bar.baz')
81
+
82
+ assert !translate_call("t(:baz, :scope => [:foo, :bar])").key_matches?(:'bar.baz')
83
+ end
84
+
85
+ def test_translate_call_key_index
86
+ assert_equal 0, translate_args("t(:foo)").key_index([:foo])
87
+ assert_equal 0, translate_args("t(:'foo.bar.baz')").key_index([:foo, :bar, :baz])
88
+ assert_equal 0, translate_args("t(:'baz.buz', :scope => [:foo, :bar])").key_index([:foo])
89
+ assert_equal 0, translate_args("t(:'baz.buz', :scope => [:foo, :bar])").key_index([:foo, :bar, :baz, :buz])
90
+
91
+ assert_equal 1, translate_args("t(:'foo.bar.baz')").key_index([:bar, :baz])
92
+ assert_equal 1, translate_args("t(:'baz.buz', :scope => [:foo, :bar])").key_index([:bar])
93
+ assert_equal 1, translate_args("t(:'baz.buz', :scope => [:foo, :bar])").key_index([:bar, :baz, :buz])
94
+
95
+ assert_equal nil, translate_args("t(:'foo.bar.baz')").key_index([:baz, :buz])
96
+ assert_equal nil, translate_args("t(:'baz.buz', :scope => [:foo, :bar])").key_index([:buz, :bar])
97
+ end
98
+ end
@@ -1,14 +1,71 @@
1
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+ $: << File.expand_path(File.dirname(__FILE__) + '/../vendor/i18n/lib')
3
+ $: << File.expand_path(File.dirname(__FILE__) + '/../vendor/ripper2ruby/lib')
4
+
1
5
  require 'test/unit'
2
- require File.dirname(__FILE__) + '/../lib/i18n/keys'
6
+ require 'fileutils'
7
+ require 'pp'
8
+
9
+ require 'i18n'
10
+ require 'i18n/commands/keys'
11
+ require 'ripper/ruby_builder'
3
12
 
4
- class String
5
- def to_sexp
6
- I18n::RubyParser.new.parse(self)
13
+ module TestRubyBuilderHelper
14
+ def sexp(src)
15
+ Ripper::SexpBuilder.new(src).parse
16
+ end
17
+
18
+ def build(src)
19
+ Ripper::RubyBuilder.build(src)
7
20
  end
8
- end
9
21
 
10
- class Sexp
11
- def find_node(type)
12
- each_of_type(type) { |node| return node }
22
+ def node(src, klass)
23
+ build(src).statement { |n| n.is_a?(klass) } or nil
13
24
  end
14
- end
25
+
26
+ def array(src)
27
+ node(src, Ruby::Array)
28
+ end
29
+
30
+ def hash(src)
31
+ node(src, Ruby::Hash)
32
+ end
33
+
34
+ def call(src)
35
+ node(src, Ruby::Call)
36
+ end
37
+
38
+ def arguments(src)
39
+ call(src).arguments
40
+ end
41
+
42
+ def method(src)
43
+ node(src, Ruby::Method)
44
+ end
45
+
46
+ def const(src)
47
+ node(src, Ruby::Const)
48
+ end
49
+ end
50
+
51
+ # class A < Array
52
+ # def +(other)
53
+ # self.dup.tap { |dup| other.each { |object| dup << object } }
54
+ # end
55
+ #
56
+ # def replace(other)
57
+ # other = self.class.new(other) unless other.is_a?(self.class)
58
+ # super
59
+ # end
60
+ # end
61
+ #
62
+ # a = A.new
63
+ # a << 1 << 2
64
+ # p a
65
+ # p a.class
66
+ # a.replace([3, 4])
67
+ # p a
68
+ # p a.class
69
+ # a += [5, 6]
70
+ # p a
71
+ # p a.class
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Fuchs
@@ -10,38 +10,43 @@ bindir: bin
10
10
  cert_chain: []
11
11
 
12
12
  date: 2009-05-26 09:00:00 +02:00
13
- default_executable: i18n-keys
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: visionmedia-commander
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - "="
22
- - !ruby/object:Gem::Version
23
- version: 3.2.9
24
- version:
13
+ default_executable:
14
+ dependencies: []
15
+
25
16
  description: Tools for Ruby/Rails I18n
26
17
  email: rails-i18n@googlegroups.com
27
- executables:
28
- - i18n-keys
18
+ executables: []
19
+
29
20
  extensions: []
30
21
 
31
22
  extra_rdoc_files: []
32
23
 
33
24
  files:
34
- - bin/i18n-keys
35
- - lib/ansi.rb
36
- - lib/i18n/keys/commands.rb
37
- - lib/i18n/keys/formatter.rb
38
- - lib/i18n/keys/index.rb
39
- - lib/i18n/keys/occurence.rb
40
- - lib/i18n/keys.rb
41
- - lib/i18n/parser/erb_parser.rb
42
- - lib/i18n/parser/ruby_parser.rb
43
- - MIT-LICENSE
44
- - README.textile
25
+ - lib/core_ext/hash/iterate_nested.rb
26
+ - lib/core_ext/hash/slice.rb
27
+ - lib/core_ext/hash/sorted_yaml_style.rb
28
+ - lib/core_ext/hash/symbolize_keys.rb
29
+ - lib/core_ext/module/attribute_accessors.rb
30
+ - lib/core_ext/object/deep_clone.rb
31
+ - lib/core_ext/object/instance_variables.rb
32
+ - lib/core_ext/object/meta_class.rb
33
+ - lib/core_ext/object/tap.rb
34
+ - lib/i18n/backend/simple_storage.rb
35
+ - lib/i18n/commands/keys.rb
36
+ - lib/i18n/exceptions/key_exists.rb
37
+ - lib/i18n/index/base.rb
38
+ - lib/i18n/index/file.rb
39
+ - lib/i18n/index/format.rb
40
+ - lib/i18n/index/key.rb
41
+ - lib/i18n/index/occurence.rb
42
+ - lib/i18n/index/simple/data.rb
43
+ - lib/i18n/index/simple/storage.rb
44
+ - lib/i18n/index/simple.rb
45
+ - lib/i18n/index.rb
46
+ - lib/i18n/ripper2ruby/translate_args_list.rb
47
+ - lib/i18n/ripper2ruby/translate_call.rb
48
+ - lib/i18n/ripper2ruby.rb
49
+ - lib/i18n/translation_properties.rb
45
50
  has_rdoc: false
46
51
  homepage: http://rails-i18n.org
47
52
  licenses: []
@@ -72,13 +77,25 @@ specification_version: 2
72
77
  summary: Tools for Ruby/Rails I18n
73
78
  test_files:
74
79
  - test/all.rb
75
- - test/commands_test.rb
76
- - test/erb_parser_test.rb
80
+ - test/core_ext/hash_iterate_nested.rb
81
+ - test/fixtures/all.rb.src
82
+ - test/fixtures/config.yml
83
+ - test/fixtures/locale/de.yml
84
+ - test/fixtures/locale/en.yml
77
85
  - test/fixtures/source_1.rb
78
86
  - test/fixtures/source_2.rb
79
87
  - test/fixtures/template.html.erb
80
- - test/index_test.rb
81
- - test/keys_test.rb
82
- - test/occurence_test.rb
83
- - test/ruby_parser_test.rb
88
+ - test/fixtures/translate/double_key.rb
89
+ - test/fixtures/translate/double_scope.rb
90
+ - test/fixtures/translate/single_key.rb
91
+ - test/fixtures/translate/single_scope.rb
92
+ - test/i18n/backend/simple_storage_test.rb
93
+ - test/i18n/backend/translation_properties_test.rb
94
+ - test/i18n/index/all.rb
95
+ - test/i18n/index/args_replace_test.rb
96
+ - test/i18n/index/calls_replace_test.rb
97
+ - test/i18n/index/commands_test.rb
98
+ - test/i18n/index/key_test.rb
99
+ - test/i18n/index/simple_test.rb
100
+ - test/i18n/ripper2ruby/translate_call_test.rb
84
101
  - test/test_helper.rb
@@ -1,20 +0,0 @@
1
- Copyright (c) 2008 Sven Fuchs <svenfuchs@artweb-design.de>
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1 +0,0 @@
1
- to turn off filename generation in zsh: unsetopt GLOB
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'commander'
5
- require File.dirname(__FILE__) + '/../lib/i18n/keys'
6
- require File.dirname(__FILE__) + '/../lib/i18n/keys/commands'
@@ -1,19 +0,0 @@
1
- module Ansi
2
- COLORS = { :red =>";31", :yellow => ";33", :green => ";32" }
3
- STYLES = { :bold => ";1", :underline => ";4" }
4
-
5
- def ansi_format(text, formats)
6
- res = "\e[0"
7
- if formats.is_a?(Array) || formats.is_a?(Hash)
8
- COLORS.each { |k,v| res += v if formats.include?(k) }
9
- STYLES.each { |k,v| res += v if formats.include?(k) }
10
- elsif formats.is_a?(Symbol)
11
- COLORS.each { |k,v| res += v if formats == k }
12
- STYLES.each { |k,v| res += v if formats == k }
13
- elsif formats.respond_to?(:to_sym)
14
- COLORS.each { |k,v| res += v if formats.to_sym == k }
15
- STYLES.each { |k,v| res += v if formats.to_sym == k }
16
- end
17
- res += "m" + text.to_s + "\e[0m"
18
- end
19
- end
@@ -1,51 +0,0 @@
1
- require File.dirname(__FILE__) + '/parser/ruby_parser'
2
- require File.dirname(__FILE__) + '/parser/erb_parser'
3
- require File.dirname(__FILE__) + '/keys/index'
4
-
5
- module I18n
6
- module Keys
7
- VERSION = '0.0.1'
8
-
9
- @@root = '.'
10
- @@verbose = true
11
-
12
- class << self
13
- def verbose?
14
- @@verbose
15
- end
16
-
17
- def verbose=(verbose)
18
- @@verbose = !!verbose
19
- end
20
-
21
- def root
22
- @@root
23
- end
24
-
25
- def root=(dir)
26
- @@root = dir
27
- end
28
-
29
- def meta_dir
30
- dir = root + '/.i18n'
31
- FileUtils.mkdir(dir) unless File.exists?(dir)
32
- dir
33
- end
34
-
35
- def config
36
- @config ||= YAML.load_file(meta_dir + '/config.yml') rescue { 'indices' => {} }
37
- end
38
-
39
- def config=(config)
40
- @config = config
41
- end
42
-
43
- def index(*args)
44
- options = args.last.is_a?(Hash) ? args.pop : {}
45
- name = args.first || options.delete(:index)
46
- index = Index.load_or_create_or_init(name, options)
47
- index
48
- end
49
- end
50
- end
51
- end
@@ -1,53 +0,0 @@
1
- program :version, I18n::Keys::VERSION
2
- program :description, 'ruby i18n tools'
3
-
4
- command :find do |c|
5
- c.syntax = 'i18n find [key] --index --verbose'
6
- c.summary = 'Find keys passed to I18n.t()'
7
- c.example 'i18n find', 'i18n find foo bar --index'
8
- c.option '--index', 'Use an index'
9
- c.option '--verbose', 'Output information about index build'
10
- c.when_called do |args, options|
11
- I18n::Keys.verbose = options.verbose
12
- index = I18n::Keys.index(:index => options.index)
13
- index.each(*args.map { |arg| arg.dup }) { |occurence| puts occurence.to_s }
14
- end
15
- end
16
-
17
- command :replace do |c|
18
- c.syntax = 'i18n replace [key] [replacement] --index --verbose'
19
- c.summary = 'Replace keys passed to I18n.t() by something else'
20
- c.example 'i18n replace', 'i18n replace foo bar --index'
21
- c.option '--index', 'Use an index'
22
- c.option '--verbose', 'Output information about index build'
23
- c.when_called do |args, options|
24
- search, replacement = args.shift, args.shift
25
- raise Commander::Runner::InvalidCommandError.new('Wrong number of arguments') unless search && replacement
26
- I18n::Keys.verbose = options.verbose
27
- index = I18n::Keys.index(:index => options.index)
28
- index.each(search.dup, replacement.dup) do |occurence|
29
- index.replace(occurence, replacement) if I18n::Commands.replace?(occurence, replacement)
30
- end
31
- end
32
- end
33
-
34
- module I18n
35
- module Commands
36
- class << self
37
- def replace?(occurence, replacement)
38
- return true if @all
39
- answer = I18n::Commands.confirm_replacement(occurence, replacement)[0, 1]
40
- answer == 'a' ? @all = true : answer == 'y'
41
- end
42
-
43
- def confirm_replacement(occurence, replacement)
44
- puts occurence.to_s, occurence.context
45
- msg = "Replace this occurence of the key \"#{occurence.key}\" with \"#{replacement}\"? [Y]es [N]o [A]ll"
46
- answer = ask(msg, %w(y yes n no a all)) do |q|
47
- q.case = :downcase
48
- q.readline = true
49
- end
50
- end
51
- end
52
- end
53
- end