svenfuchs-i18n-tools 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
data/test/test_helper.rb CHANGED
@@ -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: svenfuchs-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 00:00:00 -07: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
  post_install_message:
@@ -70,13 +75,25 @@ specification_version: 2
70
75
  summary: Tools for Ruby/Rails I18n
71
76
  test_files:
72
77
  - test/all.rb
73
- - test/commands_test.rb
74
- - test/erb_parser_test.rb
78
+ - test/core_ext/hash_iterate_nested.rb
79
+ - test/fixtures/all.rb.src
80
+ - test/fixtures/config.yml
81
+ - test/fixtures/locale/de.yml
82
+ - test/fixtures/locale/en.yml
75
83
  - test/fixtures/source_1.rb
76
84
  - test/fixtures/source_2.rb
77
85
  - test/fixtures/template.html.erb
78
- - test/index_test.rb
79
- - test/keys_test.rb
80
- - test/occurence_test.rb
81
- - test/ruby_parser_test.rb
86
+ - test/fixtures/translate/double_key.rb
87
+ - test/fixtures/translate/double_scope.rb
88
+ - test/fixtures/translate/single_key.rb
89
+ - test/fixtures/translate/single_scope.rb
90
+ - test/i18n/backend/simple_storage_test.rb
91
+ - test/i18n/backend/translation_properties_test.rb
92
+ - test/i18n/index/all.rb
93
+ - test/i18n/index/args_replace_test.rb
94
+ - test/i18n/index/calls_replace_test.rb
95
+ - test/i18n/index/commands_test.rb
96
+ - test/i18n/index/key_test.rb
97
+ - test/i18n/index/simple_test.rb
98
+ - test/i18n/ripper2ruby/translate_call_test.rb
82
99
  - test/test_helper.rb
data/MIT-LICENSE DELETED
@@ -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.
data/README.textile DELETED
@@ -1 +0,0 @@
1
- to turn off filename generation in zsh: unsetopt GLOB
data/bin/i18n-keys DELETED
@@ -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'
data/lib/ansi.rb DELETED
@@ -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
data/lib/i18n/keys.rb DELETED
@@ -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