Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Sven Fuchs committed Jul 4, 2009
1 parent 2177992 commit e02af58
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 85 deletions.
88 changes: 58 additions & 30 deletions i18n-tools.gemspec
@@ -1,40 +1,68 @@
Gem::Specification.new do |s|
s.name = "i18n-tools"
s.version = "0.0.4"
s.version = "0.0.5"
s.date = "2009-05-26"
s.summary = "Tools for Ruby/Rails I18n"
s.email = "rails-i18n@googlegroups.com"
s.homepage = "http://rails-i18n.org"
s.description = "Tools for Ruby/Rails I18n"
s.has_rdoc = false
s.authors = ['Sven Fuchs']
s.files = [
'bin/i18n-keys',
'lib/ansi.rb',
'lib/i18n/keys/commands.rb',
'lib/i18n/keys/format.rb',
'lib/i18n/keys/index.rb',
'lib/i18n/keys/call.rb',
'lib/i18n/keys.rb',
'lib/i18n/parser/erb_parser.rb',
'lib/i18n/parser/ruby_parser.rb',
'MIT-LICENSE',
'README.textile'
]
s.test_files = [
'test/all.rb',
'test/commands_test.rb',
'test/erb_parser_test.rb',
'test/fixtures/source_1.rb',
'test/fixtures/source_2.rb',
'test/fixtures/template.html.erb',
'test/index_test.rb',
'test/keys_test.rb',
'test/call_test.rb',
'test/ruby_parser_test.rb',
'test/test_helper.rb'
]
s.add_dependency('visionmedia-commander', ['= 3.2.9'])
s.executables = ['i18n-keys']
s.default_executable = 'i18n-keys'
s.files = %w(
lib/core_ext/hash/iterate_nested.rb
lib/core_ext/hash/slice.rb
lib/core_ext/hash/sorted_yaml_style.rb
lib/core_ext/hash/symbolize_keys.rb
lib/core_ext/module/attribute_accessors.rb
lib/core_ext/object/deep_clone.rb
lib/core_ext/object/instance_variables.rb
lib/core_ext/object/meta_class.rb
lib/core_ext/object/tap.rb
lib/i18n/backend/simple_storage.rb
lib/i18n/commands/keys.rb
lib/i18n/exceptions/key_exists.rb
lib/i18n/index/base.rb
lib/i18n/index/file.rb
lib/i18n/index/format.rb
lib/i18n/index/key.rb
lib/i18n/index/occurence.rb
lib/i18n/index/simple/data.rb
lib/i18n/index/simple/storage.rb
lib/i18n/index/simple.rb
lib/i18n/index.rb
lib/i18n/ripper2ruby/ruby_builder.rb
lib/i18n/ripper2ruby/translate_args_list.rb
lib/i18n/ripper2ruby/translate_call.rb
lib/i18n/ripper2ruby.rb
lib/i18n/translation_properties.rb
MIT-LICENSE
README.markdown
)
s.test_files = %w(
test/all.rb
test/core_ext/hash_iterate_nested.rb
test/fixtures/all.rb.src
test/fixtures/config.yml
test/fixtures/locale/de.yml
test/fixtures/locale/en.yml
test/fixtures/source_1.rb
test/fixtures/source_2.rb
test/fixtures/template.html.erb
test/fixtures/translate/double_key.rb
test/fixtures/translate/double_scope.rb
test/fixtures/translate/single_key.rb
test/fixtures/translate/single_scope.rb
test/i18n/backend/simple_storage_test.rb
test/i18n/backend/translation_properties_test.rb
test/i18n/index/all.rb
test/i18n/index/args_replace_test.rb
test/i18n/index/calls_replace_test.rb
test/i18n/index/commands_test.rb
test/i18n/index/key_test.rb
test/i18n/index/simple_test.rb
test/i18n/ruby/translate_call_test.rb
test/test_helper.rb )
# s.add_dependency('svenfuchs-ripper2ruby', ['>= 0.0.1'])
# s.executables = ['i18n-keys']
# s.default_executable = 'i18n-keys'
end
5 changes: 4 additions & 1 deletion i18n-tools.thor
@@ -1,4 +1,7 @@
require 'rubygems'
$:.unshift File.expand_path('/Users/sven/Development/projects/i18n/i18n-tools/lib')
$:.unshift File.expand_path('/Users/sven/Development/projects/i18n/i18n-tools/vendor/ripper2ruby/lib')
# require 'rubygems'

require 'thor'
require 'ripper2ruby'
require 'i18n/commands/keys'
Expand Down
4 changes: 2 additions & 2 deletions lib/i18n/commands/keys.rb
Expand Up @@ -7,15 +7,15 @@
module I18n
module Commands
class Keys
def initialize(highlighter = Highlighters::Ansi.new(:red, :bold), out = $stdout)
def initialize(highlighter = Highlighters::Ansi.new(:bold), out = $stdout)
@highlighter = highlighter
@out = out
end

def find(keys, options = {})
index = index(options)
index.find_calls(*keys).each do |call|
log "\n" + call.to_s(:context => options[:context], :highlight => @highlighter)
log "\n" + call.to_s(:context => options[:context], :highlight => @highlighter).gsub(Dir.pwd, '')
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/i18n/index.rb
Expand Up @@ -6,11 +6,11 @@

module I18n
module Index
mattr_accessor :default_pattern, :implementation, :parser, :filters
mattr_accessor :pattern, :implementation, :parser, :filters

@@implementation = I18n::Index::Simple
@@parser = I18n::Ripper::RubyBuilder
@@filters = { :erb => lambda { |source| Erb::Stripper.new.to_ruby(source) } }
@@filters = { '.erb' => lambda { |source| Erb::Stripper.new.to_ruby(source) } }
@@pattern = '**/*.{rb,erb}'

class << self
Expand All @@ -24,7 +24,7 @@ def load_or_create(*args)

def filter(source, filename)
filters.each do |extname, filter|
source = filter.call(source) if ::File.extname(filename)[1, -1] == extname.to_s
source = filter.call(source) if ::File.extname(filename) == extname
end
source
end
Expand Down
2 changes: 1 addition & 1 deletion lib/i18n/base.rb → lib/i18n/index/base.rb
Expand Up @@ -7,7 +7,7 @@ class Base

def initialize(options = {})
@root_dir = options[:root_dir] || Dir.pwd
@pattern = options[:pattern] || Index.default_pattern
@pattern = options[:pattern] || Index.pattern
options[:format].setup(self) if options[:format]
end

Expand Down
12 changes: 6 additions & 6 deletions lib/i18n/index/file.rb
Expand Up @@ -9,7 +9,7 @@ def [](filename)
end

class File
attr_accessor :path, :source
attr_accessor :path

def initialize(path)
self.path = path
Expand All @@ -20,26 +20,26 @@ def source
end

def ruby
parser.ruby
@ruby ||= parser.parse
end

def calls
parser.translate_calls
@calls ||= ruby.select_translate_calls
end

def update(source)
self.source = source
@source = source
save
end

def save
::File.open(path, 'w+') { |f| f.write(source) }
::File.open(path, 'w+') { |f| f.write(source) } # TODO need to modify/write unfiltered source for ERB
end

protected

def parser
@parser ||= Index.parser.new(source, path).tap { |p| p.parse }
@parser ||= Index.parser.new(source, path)
end
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/i18n/index/format.rb
Expand Up @@ -39,7 +39,6 @@ def save
end

def parse(file)
# puts " parsing #{::File.expand_path(file)}"
format.out '.'
super
end
Expand Down
7 changes: 3 additions & 4 deletions lib/i18n/index/simple.rb
@@ -1,4 +1,4 @@
require 'i18n/base'
require 'i18n/index/base'
require 'i18n/index/key'
require 'i18n/index/occurence'
require 'i18n/index/format'
Expand All @@ -14,15 +14,14 @@ class Simple < Base
def find_call(*keys)
return unless key = data.keys.detect { |key, data| key.matches?(*keys) }
occurence = data.occurences(key).first
# TODO cache parsed files on Index
files[occurence.filename].ruby.select(Ruby::Call, :position => occurence.position).first
files[occurence.filename].ruby.select_translate_calls(:position => occurence.position).first
end

def find_calls(*keys)
keys = data.keys.select { |key, data| key.matches?(*keys) }
occurences = keys.map { |key| data.occurences(key) }.flatten
occurences.map do |occurence|
files[occurence.filename].ruby.select(Ruby::Call, :position => occurence.position)
files[occurence.filename].ruby.select_translate_calls(:position => occurence.position)
end.flatten
end

Expand Down
43 changes: 22 additions & 21 deletions lib/i18n/ripper2ruby/ruby_builder.rb
@@ -1,27 +1,28 @@
module I18n
module Ripper
class RubyBuilder < ::Ripper::RubyBuilder
def on_stmts_add(target, statement)
super.tap do
collect_translate_call(statement.to_translate_call) if statement.is_a?(Ruby::Call)
end
end

def translate_calls
@translate_calls ||= []
end

def collect_translate_call(call)
call.tap { |c| translate_calls << c } if is_translate_call?(call)
end

KEY_CLASSES = [Ruby::Symbol, Ruby::DynaSymbol, Ruby::String, Ruby::Array]

def is_translate_call?(call)
call.identifier.try(:token) == 't' &&
(!call.target.respond_to?(:token) || call.target.token == 'I18n') &&
call.arguments && KEY_CLASSES.include?(call.arguments.first.arg.class)
end
# def on_stmts_add(target, statement)
# super.tap do
# statement = statement.select(Ruby::Call) unless statement.nil? || statement.is_a?(Ruby::Call)
# collect_translate_call(statement.to_translate_call) if statement.is_a?(Ruby::Call)
# end
# end
#
# def translate_calls
# @translate_calls ||= []
# end
#
# def collect_translate_call(call)
# call.tap { |c| translate_calls << c } if is_translate_call?(call)
# end
#
# KEY_CLASSES = [Ruby::Symbol, Ruby::DynaSymbol, Ruby::String, Ruby::Array]
#
# def is_translate_call?(call)
# call.identifier.try(:token) == 't' &&
# (!call.target.respond_to?(:token) || call.target.token == 'I18n') &&
# call.arguments && KEY_CLASSES.include?(call.arguments.first.arg.class)
# end
end
end
end
2 changes: 1 addition & 1 deletion lib/i18n/ripper2ruby/translate_args_list.rb
Expand Up @@ -13,7 +13,7 @@ def full_key(joined = false)
end

def key
eval(first.to_ruby) if first
first.arg.value if first
end

def scope
Expand Down
38 changes: 34 additions & 4 deletions lib/i18n/ripper2ruby/translate_call.rb
@@ -1,10 +1,39 @@
module Ruby
class Node
def select_translate_calls(*args)
select(Ruby::Call, *args) { |node| node.is_translate_call? }.map { |call| call.to_translate_call }
end

def is_translate_call?
false
end
end

class Call
def to_translate_call
meta_class.send(:include, TranslateCall)
arguments.to_translate_args_list if arguments.respond_to?(:to_translate_args_list)
unless meta_class.include?(TranslateCall)
meta_class.send(:include, TranslateCall)
arguments.to_translate_args_list if arguments.respond_to?(:to_translate_args_list)
end
self
end

def is_translate_call?
identifier.try(:token) == 't' &&
is_translate_method_target?(target) &&
is_translate_key?(arguments.first.try(:arg))
end

protected

def is_translate_method_target?(target)
target.nil? || target.try(:identifier).try(:token) == 'I18n'
end

def is_translate_key?(arg)
# TODO ... what to do with Arrays? what to do with DynaSymbols w/ embedded expressions?
arg && [Ruby::Symbol, Ruby::DynaSymbol, Ruby::String].include?(arg.class) && arg.try(:value)
end
end

module TranslateCall
Expand All @@ -29,8 +58,9 @@ def replace_key(search, replacement)
end

def to_s(options = {})
"#{key}: #{filename} [#{row}/#{column}]\n" +
(options.has_key?(:context) ? self.context(options.update(:width => options[:context].to_i)) : '')
context = (options.has_key?(:context) ? self.context(options.update(:width => options[:context].to_i)) : '')
context = context.split("\n").map(&:strip).join("\n")
"#{key}: #{filename} [#{row}/#{column}]\n" + context
end
end
end
14 changes: 7 additions & 7 deletions test/i18n/index/simple_test.rb
Expand Up @@ -10,7 +10,7 @@ def setup
@index = I18n::Index::Simple.new(:root_dir => @root_dir, :pattern => File.basename(@filename))
FileUtils.cp(@filename, "#{@filename}.backup")
end

def teardown
@index.delete
FileUtils.mv("#{@filename}.backup", @filename)
Expand All @@ -22,8 +22,8 @@ def assert_valid_index(index)
assert_equal 'fixtures', File.basename(index.root_dir)

keys = [:baaar, :bar, :bar_1, :"baz.fooo.baar", :"foo.bar"]
assert_equal keys.sort, index.send(:data).keys.map(&:key).sort
assert_equal 2, index.send(:data)[:bar][:occurences].size
assert_equal keys.sort, index.data.keys.map(&:key).sort
assert_equal 2, index.data[:bar][:occurences].size

occurence = index.send(:data)[:bar][:occurences].first
assert_equal :bar, occurence.key.key # yuck
Expand All @@ -40,24 +40,24 @@ def assert_valid_index(index)
index = I18n::Index::Simple.send(:load, :root_dir => @root_dir)
assert_valid_index(index)
end

define_method :"test finds a call" do
assert_equal 't(:bar)', @index.find_call(:bar).to_ruby
end

define_method :"test subsequently replaces keys" do
@index.update # build and save

call = @index.find_call(:bar)
assert call

@index.replace_key(call, :bar, :bazooh)
assert File.read(@filename) =~ /:bazooh/

index = I18n::Index::Simple.send(:load, :root_dir => @root_dir) # reload the index
call = index.find_call(:bar)
assert call

index.replace_key(call, :bar, :bazuuh)
assert File.read(@filename) =~ /:bazuuh/

Expand Down

0 comments on commit e02af58

Please sign in to comment.