Skip to content

Commit

Permalink
Hello i18n-debug
Browse files Browse the repository at this point in the history
  • Loading branch information
fphilipe committed Jun 7, 2014
0 parents commit 1cbfba5
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
Gemfile.lock
*.gem
2 changes: 2 additions & 0 deletions Gemfile
@@ -0,0 +1,2 @@
source 'https://rubygems.org'
gemspec
22 changes: 22 additions & 0 deletions LICENSE.txt
@@ -0,0 +1,22 @@
Copyright (c) 2014 Philipe Fatio

MIT License

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
77 changes: 77 additions & 0 deletions README.md
@@ -0,0 +1,77 @@
# Ruby I18n Debug

**Ever wondered which translations are being looked up by Rails, a gem, or
simply your app? Wonder no more!**

Rails' implicit translations, for instance, are a nice feature. But sometimes
getting the key to, let's say, the `BillingAddress`' `street` attribute in
a nested form inside an `Order` can be quite tricky to get right on the first
try. The key for this example would be
`activerecord.attributes.order/billing_address.street`. Good luck figuring that
out!

With this gem you can easily see which translations are being looked up. The key
above would have created the following debug log entry:

```
[i18n-debug] activerecord.attributes.order/billing_address.name => nil
```

After setting the translation for that key you just discovered, the log entry
changes to this:

```
[i18n-debug] activerecord.attributes.order/billing_address.name => "Order billing name"
```

## Installation

Simply add the gem to your `Gemfile`. You probably only want this in development.
Thus, place it inside the `development` group.

```ruby
gem 'i18n-debug', group: :development
```

## Usage

This gem works straight out of the box. If Rails is available, it will log using
`Rails.logger.debug`. Otherwise it will log using `Logger.new($stdout).debug`.

If you wish to use a custom logger, simply set it as follows (make sure it
responds to `debug`):

```ruby
I18n::Debug.logger = my_custom_logger
```

Every lookup invokes the lambda `I18n::Debug.on_lookup` with the key and the
translation value as arguments. The default lambda simply logs it to the logger
mentioned above. If you want to change the logging format or do something
totally different, simply set your own handler to do so:

```ruby
# Collect stats on I18n key usage.
i18n_stats = Hash.new { |stats, key| stats[key] = 0 }

I18n::Debug.on_lookup = lambda do |key, value|
i18n_stats[key] += 1 if value
end
```

## Additional Information

This gem was inspired by a similar gem called
[rails-i18n-debug](https://github.com/256dpi/rails-i18n-debug).

### Dependencies

- [i18n](https://github.com/svenfuchs/i18n)

### Author

Philipe Fatio ([fphilipe](https://github.com/fphilipe))

### License

MIT License. Copyright 2014 Philipe Fatio
8 changes: 8 additions & 0 deletions Rakefile
@@ -0,0 +1,8 @@
require 'bundler/gem_tasks'
require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
t.libs << 'test'
end

task :default => :test
16 changes: 16 additions & 0 deletions i18n-debug.gemspec
@@ -0,0 +1,16 @@
require_relative 'lib/i18n/debug/version'

Gem::Specification.new do |spec|
spec.name = 'i18n-debug'
spec.version = I18n::Debug::VERSION
spec.author = 'Philipe Fatio'
spec.email = 'me@phili.pe'
spec.homepage = 'https://github.com/fphilipe/i18n-debug'
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0")
spec.test_files = `git ls-files -z -- test`.split("\x0")
spec.summary = %q{Ever wondered which translations are being looked up by Rails, a gem, or simply your app? Wonder no more!}
spec.description = spec.summary

spec.add_dependency 'i18n', '~> 0.0'
end
44 changes: 44 additions & 0 deletions lib/i18n/debug.rb
@@ -0,0 +1,44 @@
require 'i18n'
require 'i18n/debug/version'

module I18n
module Debug
@on_lookup = lambda do |key, result|
logger.debug("[i18n-debug] #{key} => #{result.inspect}")
end

class << self
attr_accessor :logger, :on_lookup

def logger
@logger ||=
if defined?(::Rails)
::Rails.logger
else
require 'logger'
::Logger.new($stdout)
end
end
end

module Hook
def self.included(klass)
klass.class_eval do
alias_method :lookup_without_debug, :lookup
alias_method :lookup, :lookup_with_debug
end
end

def lookup_with_debug(*args)
lookup_without_debug(*args).tap do |result|
options = args.last.is_a?(Hash) ? args.pop : {}
separator = options[:separator] || I18n.default_separator
key = I18n.normalize_keys(*args, separator).join(separator)
Debug.on_lookup[key, result]
end
end
end
end

Backend::Simple.include(Debug::Hook)
end
5 changes: 5 additions & 0 deletions lib/i18n/debug/version.rb
@@ -0,0 +1,5 @@
module I18n
module Debug
VERSION = '1.0.0'
end
end
42 changes: 42 additions & 0 deletions test/test_i18n_debug.rb
@@ -0,0 +1,42 @@
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'i18n/debug'
require 'minitest/autorun'

class TestI18nDebug < Minitest::Test
alias_method :silence_io, :capture_io

def setup
I18n.backend.store_translations(:en, foo: { bar: 'baz' })
# Avoid I18n deprecation warning:
I18n.enforce_available_locales = true
# Reset logger to its initial state:
I18n::Debug.logger = nil
end

def test_does_not_alter_default_i18n_behavior
silence_io do
assert_equal I18n.t('foo.bar'), 'baz'
end
end

def test_logger_invoked
assert_output(/en\.foo\.bar => "baz"/) do
I18n.t('foo.bar')
end
end

def test_custom_lookup_hook_called
default_hook = I18n::Debug.on_lookup
hook_key, hook_value = nil
I18n::Debug.on_lookup = lambda do |key, value|
hook_key, hook_value = key, value
end

I18n.t('foo.bar')

assert_equal hook_key, 'en.foo.bar'
assert_equal hook_value, 'baz'
ensure
I18n::Debug.on_lookup = default_hook
end
end

0 comments on commit 1cbfba5

Please sign in to comment.