glebm / i18n-tasks

Manage translation and localization with static analysis, for Ruby i18n
http://glebm.github.io/i18n-tasks
MIT License
2.07k stars 262 forks source link

"Unused" doesn't work #75

Closed khelal closed 10 years ago

khelal commented 10 years ago

Given this config file:

base_locale: en
locales: [en, ar, fr]
data:
  adapter: I18n::Tasks::Data::FileSystem
  read:
  - config/locales/*/*%{locale}.yml
  write:
  - config/locales/%{locale}.yml
relative_roots:
- app/controllers
- app/helpers
- app/views
search:
  scanner: I18n::Tasks::Scanners::PatternWithScopeScanner
  relative_roots:
  - app/
  paths:
  - app
  exclude:
  - "*.jpg"
  - "*.png"
  - "*.gif"
  - "*.svg"
  - "*.ico"
  - "*.eot"
  - "*.ttf"
  - "*.woff"
  - "*.pdf"
  ignore_lines:
  - "^\\s*[#/](?!\\si18n-tasks-use)"

When i run "bundle exec i18n-tasks unused" it tells me that I have 0 unused strings, altho I know for a fact that this is not right as I added a couple of random strings in there.

glebm commented 10 years ago

Perhaps master works for you?

gem 'i18n-tasks', git: 'https://github.com/glebm/i18n-tasks'
$ bundle update i18n-tasks
$ bundle exec i18n-tasks unused
khelal commented 10 years ago

No, I now get the following error:

➜  protenders git:(master) ✗ bundle exec i18n-tasks unused
/Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/siblings.rb:56:in `set': undefined method `set' for nil:NilClass (NoMethodError)
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/siblings.rb:131:in `block (2 levels) in from_key_attr'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/siblings.rb:127:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/siblings.rb:127:in `block in from_key_attr'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/siblings.rb:120:in `call'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/siblings.rb:120:in `build_forest'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/siblings.rb:126:in `from_key_attr'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/used_keys.rb:17:in `used_tree'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/used_keys.rb:30:in `used_key_names'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/used_keys.rb:47:in `expr_key_re'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/used_keys.rb:41:in `used_in_expr?'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/unused_keys.rb:15:in `block in unused_tree'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:92:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:92:in `block in select_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:52:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:52:in `block in keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:13:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:13:in `block in leaves'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:40:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:7:in `nodes'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:12:in `leaves'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:52:in `keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/data/tree/traversal.rb:91:in `select_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/unused_keys.rb:13:in `unused_tree'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/unused_keys.rb:9:in `block in unused_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/unused_keys.rb:9:in `map'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/unused_keys.rb:9:in `unused_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/commands.rb:28:in `block in <class:Commands>'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/commands_base.rb:40:in `instance_exec'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/lib/i18n/tasks/commands_base.rb:40:in `block in cmd'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-eefacc4db147/bin/i18n-tasks:52:in `<top (required)>'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bin/i18n-tasks:23:in `load'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bin/i18n-tasks:23:in `<main>'
glebm commented 10 years ago

I wonder what keys are coming from the scanner?

$ i18n-tasks irb
> scanner.keys
# or
> scanner.keys.map(&:first).grep(/[^\w.-]/)
khelal commented 10 years ago
2.1.1 :002 > scanner.keys.map(&:first).grep(/[^\w.-]/)
 => ["states.\#{task.state}", "flash.projects.\#{action}.successful", "flash.tender.\#{action}.successful", "nagger.\#{sym}", "nagger.\#{project_nagger.next_step}", "event_actions.\#{event_type}.\#{action}", "fee.\#{fee_type}", "\#{label}", "pages.benefits.questions.q\#{i}", "pages.benefits.questions.a\#{i}", "pages.benefits.consultants.benefit\#{i}", "pages.benefits.consultants.benefit\#{i}_sub", "pages.benefits.consultants.feature\#{i}_\#{j}_head", "pages.benefits.consultants.feature\#{i}_\#{j}_text", "pages.benefits.contractors.benefit\#{i}", "pages.benefits.contractors.benefit\#{i}_sub", "pages.benefits.contractors.feature\#{i}_\#{j}_head", "pages.benefits.contractors.feature\#{i}_\#{j}_text", "pages.benefits.developers.benefit\#{i}", "pages.benefits.developers.benefit\#{i}_sub", "pages.benefits.developers.feature\#{i}_\#{j}_head", "pages.benefits.developers.feature\#{i}_\#{j}_text", "pages.benefits.subcontractors.benefit\#{i}", "pages.benefits.subcontractors.benefit\#{i}_sub", "pages.benefits.subcontractors.feature\#{i}_\#{j}_head", "pages.benefits.subcontractors.feature\#{i}_\#{j}_text", "pages.benefits.suppliers.benefit\#{i}", "pages.benefits.suppliers.benefit\#{i}_sub", "pages.benefits.suppliers.feature\#{i}_\#{j}_head", "pages.benefits.suppliers.feature\#{i}_\#{j}_text", "\#{displayed_text}", "\#{document_set.state}"]

I tried posting the result of scanner.keys, but it's too long for github.

2.1.1 :004 > scanner.keys.size
 => 1566
glebm commented 10 years ago

Pushed what may be a fix to master https://github.com/glebm/i18n-tasks/commit/5775bc3ad27e9f4501f188c7d174a935bdce71fd

khelal commented 10 years ago

Same problem :(

➜  protenders git:(master) ✗ bundle exec i18n-tasks unused
/Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/siblings.rb:58:in `set': undefined method `set' for nil:NilClass (NoMethodError)
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/siblings.rb:135:in `block (2 levels) in from_key_attr'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/siblings.rb:131:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/siblings.rb:131:in `block in from_key_attr'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/siblings.rb:124:in `call'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/siblings.rb:124:in `build_forest'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/siblings.rb:130:in `from_key_attr'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/used_keys.rb:17:in `used_tree'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/used_keys.rb:30:in `used_key_names'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/used_keys.rb:47:in `expr_key_re'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/used_keys.rb:41:in `used_in_expr?'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/unused_keys.rb:15:in `block in unused_tree'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:92:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:92:in `block in select_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:52:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:52:in `block in keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:13:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:13:in `block in leaves'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:40:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `yield'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/node.rb:40:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:42:in `block (2 levels) in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:41:in `block in depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/nodes.rb:13:in `each'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:39:in `depth_first'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:7:in `nodes'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:12:in `leaves'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:52:in `keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/data/tree/traversal.rb:91:in `select_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/unused_keys.rb:13:in `unused_tree'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/unused_keys.rb:9:in `block in unused_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/unused_keys.rb:9:in `map'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/unused_keys.rb:9:in `unused_keys'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/commands.rb:28:in `block in <class:Commands>'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/commands_base.rb:40:in `instance_exec'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/lib/i18n/tasks/commands_base.rb:40:in `block in cmd'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bundler/gems/i18n-tasks-7a1a288085cd/bin/i18n-tasks:52:in `<top (required)>'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bin/i18n-tasks:23:in `load'
    from /Users/khelal/.rvm/gems/ruby-2.1.1@monaqasat/bin/i18n-tasks:23:in `<main>'
khelal commented 10 years ago

here is my config file, for reference:

base_locale: en
locales:
- en
data:
  adapter: I18n::Tasks::Data::FileSystem
  read:
  - config/locales/*/*.%{locale}.yml
  write:
  - config/locales/%{locale}.yml
relative_roots:
- app/controllers
- app/helpers
- app/views
search:
  scanner: I18n::Tasks::Scanners::PatternWithScopeScanner
  relative_roots:
  - app/views
  paths:
  - app/
  exclude:
  - "*.jpg"
  - "*.png"
  - "*.gif"
  - "*.svg"
  - "*.ico"
  - "*.eot"
  - "*.ttf"
  - "*.woff"
  - "*.pdf"
  ignore_lines:
  - "^\\s*[#/](?!\\si18n-tasks-use)"
glebm commented 10 years ago

The config looks OK. It fails when creating a tree from scanner.keys:

Tree::Siblings.from_key_attr scanner.keys

I don't know which key is causing the problem, but I should be able to reproduce this if I have scanner.keys, can you share it in a private gist or by email? My email is glex.spb at gmail.

Please switch to branch next:

gem 'i18n-tasks', git: 'https://github.com/glebm/i18n-tasks', branch: 'next'
glebm commented 10 years ago

Nevermind, I now know what's wrong, will push a fix shortly (better error message on namespace/leaf conflict)

glebm commented 10 years ago

As part of implementation, i18n-tasks merges locales trees together. This error can happen when merging trees like these two:

Tree A:

common: Common

Tree B:

common: 
  hello: Hello

Tree A + Tree B :boom:

I am not yet sure what i18n-tasks should do in this case, but I've added an error message that tells which key is causing this on branch next.

glebm commented 10 years ago

^ issue a warning and not :boom:

glebm commented 10 years ago

0.6.0 is now out with this issue fixed, please reopen if still broken

khelal commented 10 years ago

Hi,

Unfortunately it doesn't work quite well yet. Here's with the latest version:

➜  protenders git:(master) ✗ i18n-tasks unused
i18n-tasks: [WARN] 'protenders' was a leaf, now has children (value <- scope conflict)
Unused keys (0) | i18n-tasks v0.6.1
Good job! Every translation is used!

And here's my config file:

base_locale: en
locales:
- en
data:
  adapter: I18n::Tasks::Data::FileSystem
  read:
  - config/locales/*/*.en.yml
  write:
  - config/locales/%{locale}.yml
search:
  scanner: I18n::Tasks::Scanners::PatternWithScopeScanner
  relative_roots:
  - app/views
  - app/controllers
  - app/helpers
  paths:
  - app/
  exclude:
  - "*.jpg"
  - "*.png"
  - "*.gif"
  - "*.svg"
  - "*.ico"
  - "*.eot"
  - "*.ttf"
  - "*.woff"
  - "*.pdf"
  ignore_lines:
  - "^\\s*[#/](?!\\si18n-tasks-use)"

Regarding the "i18n-tasks: [WARN] 'protenders' was a leaf, now has children (value <- scope conflict)" warning message, I have searched through my locale files and although i DID initially ahve this conflict, I removed it but still have the message that appears.

Also, for sanity, is it possible to display the total number of keys that are being read as I have a feeling that he's not picking up all my locale files.

glebm commented 10 years ago

If the message is showing, the problem is still present, run:

git grep 'protenders:' -- config/locales/**/*.yml

You can check the keys like this from i18n-tasks irb:

> tree('en')
> tree('en').leaves.count
> guide # learn more
khelal commented 10 years ago

This is what i get after running the grep command:

git grep 'protenders:' -- config/locales/**/*en.yml
config/locales/en.yml:      protenders: "PROTENDERS"
config/locales/en.yml:    my_protenders: "My Tenders"
config/locales/en.yml:  protenders:
config/locales/others/devise.en.yml:      welcome_to_protenders: "Welcome to ProTenders"
config/locales/views/layouts/protenders.en.yml:    protenders:

Notice that the 3 different "protenders" are all at different levels (companies.transactions.protenders, protenders, layout.protenders) or under other keys, so they shouldn't be conflicting...

glebm commented 10 years ago

According to the message there is a conflict on the top level (it is not necessarily en).

khelal commented 10 years ago

With the latest version (0.6.1) freshly installed, I don't get that warning anymore, but it still shows me that there are no unused keys even tho I've added a totally random one at the top of the file.

➜  protenders git:(master) ✗ i18n-tasks irb
i18n-tasks v0.6.1 IRB
Type guide to learn more
2.1.1 :001 > tree('en').leaves.count
 => 2749
2.1.1 :002 > exit
➜  protenders git:(master) ✗ i18n-tasks unused
Unused keys (0) | i18n-tasks v0.6.1
Well done! Every translation is used!

and I've added the following key at the top of my "en.yml" file:

en:
  yomymadsdssdsdsn: "toototot"
  i18ntasktest: "This is never called anywhere"
  accept: accept
  .....
glebm commented 10 years ago

Dynamic key matching was too aggressive, changed on master, does it work? Use bundle exec when running

khelal commented 10 years ago

hehe now it does work, but i get a feeling it's too soft. I get 1334 unused keys, which I doubt is correct :) let me go through these results and see if they make any sense.

glebm commented 10 years ago

:8ball: Might need an option to ignore dynamic usages (not consider category.books used when I18n.t("category.#{category.key}") is seen in the code).

glebm commented 10 years ago

If the unused keys are Rails magic keys (model attribute names etc), there are two options:

A) Mark the usages with an explicit comment (had not been documented before):

# i18n-tasks-use t('activerecord.models.user')
User.model_name.human

B) Alternatively, add the keys to config ignore_unused, perhaps using a * match.

glebm commented 10 years ago

Added a strict mode to unused on master. With --strict it does not attempt to infer used keys from dynamic calls:

i18n-tasks unused --strict