From bcdfede0a7e528c805eb3c8b92712b7541f75648 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sat, 6 Nov 2010 11:30:55 +0100 Subject: [PATCH] extract I18n::MissingTranslations from adva-cms2 --- .gitignore | 1 + Gemfile | 4 +++ Gemfile.lock | 24 +++++++++++++ README.textile | 0 Rakefile | 10 ++++++ i18n-missing_translations.gemspec | 22 ++++++++++++ lib/i18n/missing_translations.rb | 43 ++++++++++++++++++++++ lib/i18n/missing_translations/handler.rb | 10 ++++++ lib/i18n/missing_translations/log.rb | 33 +++++++++++++++++ lib/i18n/missing_translations/version.rb | 5 +++ test/missing_translations_test.rb | 45 ++++++++++++++++++++++++ test/test_helper.rb | 7 ++++ 12 files changed, 204 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 README.textile create mode 100644 Rakefile create mode 100644 i18n-missing_translations.gemspec create mode 100644 lib/i18n/missing_translations.rb create mode 100644 lib/i18n/missing_translations/handler.rb create mode 100644 lib/i18n/missing_translations/log.rb create mode 100644 lib/i18n/missing_translations/version.rb create mode 100644 test/missing_translations_test.rb create mode 100644 test/test_helper.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c913e96 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.bundle/* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..d138858 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source :rubygems +gemspec + +gem 'i18n', :git => 'git://github.com/svenfuchs/i18n.git', :ref => '0.5.0' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..9c3a871 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,24 @@ +GIT + remote: git://github.com/svenfuchs/i18n.git + revision: 23c9feffea8f23f686020b64770ca4dae030b545 + ref: 0.5.0 + specs: + i18n (0.4.2) + +PATH + remote: . + specs: + i18n-missing_translations (0.0.1) + +GEM + remote: http://rubygems.org/ + specs: + test_declarative (0.0.4) + +PLATFORMS + ruby + +DEPENDENCIES + i18n! + i18n-missing_translations! + test_declarative diff --git a/README.textile b/README.textile new file mode 100644 index 0000000..e69de29 diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..47e7ef4 --- /dev/null +++ b/Rakefile @@ -0,0 +1,10 @@ +require 'rake' +require 'rake/testtask' + +Rake::TestTask.new do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + +task :default => :test diff --git a/i18n-missing_translations.gemspec b/i18n-missing_translations.gemspec new file mode 100644 index 0000000..617a2e7 --- /dev/null +++ b/i18n-missing_translations.gemspec @@ -0,0 +1,22 @@ +# encoding: utf-8 + +$:.unshift File.expand_path('../lib', __FILE__) +require 'i18n/missing_translations/version' + +Gem::Specification.new do |s| + s.name = "i18n-missing_translations" + s.version = I18n::MissingTranslations::VERSION + s.authors = ["Sven Fuchs"] + s.email = "svenfuchs@artweb-design.de" + s.homepage = "http://github.com/svenfuchs/i18n-missing_translations" + s.summary = "[summary]" + s.description = "[description]" + + s.files = `git ls-files app lib`.split("\n") + s.platform = Gem::Platform::RUBY + s.require_path = 'lib' + s.rubyforge_project = '[none]' + + # s.add_dependency 'i18n', '~> 0.5.0' + s.add_development_dependency 'test_declarative' +end diff --git a/lib/i18n/missing_translations.rb b/lib/i18n/missing_translations.rb new file mode 100644 index 0000000..9f1060c --- /dev/null +++ b/lib/i18n/missing_translations.rb @@ -0,0 +1,43 @@ +require 'i18n' +require 'i18n/exceptions' + +module I18n + class << self + attr_writer :missing_translations + + def missing_translations + @missing_translations ||= MissingTranslations::Log.new + end + end + + class MissingTranslations + autoload :Log, 'i18n/missing_translations/log' + autoload :Handler, 'i18n/missing_translations/handler' + + attr_reader :app, :filename + + def initialize(app, filename = nil) + @app = app + @filename = filename || guess_filename + end + + def call(*args) + log.read(filename) + app.call(*args).tap { log.write(filename) } + end + + def log + I18n.missing_translations + end + + def guess_filename + if File.directory?("#{Dir.pwd}/log") + "#{Dir.pwd}/log/missing_translations.log" + else + "/tmp/#{File.dirname(Dir.pwd)}-missing_translations.log" + end + end + end + + ExceptionHandler.send(:include, MissingTranslations::Handler) +end diff --git a/lib/i18n/missing_translations/handler.rb b/lib/i18n/missing_translations/handler.rb new file mode 100644 index 0000000..560f5e7 --- /dev/null +++ b/lib/i18n/missing_translations/handler.rb @@ -0,0 +1,10 @@ +module I18n + class MissingTranslations + module Handler + def call(exception, locale, key, options) + I18n.missing_translations.log(exception.keys) if MissingTranslationData === exception + super + end + end + end +end diff --git a/lib/i18n/missing_translations/log.rb b/lib/i18n/missing_translations/log.rb new file mode 100644 index 0000000..8befa48 --- /dev/null +++ b/lib/i18n/missing_translations/log.rb @@ -0,0 +1,33 @@ +require 'yaml' +require 'fileutils' + +module I18n + class MissingTranslations + class Log < Hash + def log(keys) + keys = keys.dup + key = keys.pop.to_s + log = keys.inject(self) { |log, k| log.key?(k.to_s) ? log[k.to_s] : log[k.to_s] = {} } + log[key] = key.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize } + end + + def dump(out = $stdout) + out.puts(to_yml) unless empty? + end + + def read(filename) + data = YAML.load_file(filename) rescue nil + self.replace(data) if data + end + + def write(filename) + FileUtils.mkdir_p(File.dirname(filename)) + File.open(filename, 'w+') { |f| f.write(to_yml) } + end + + def to_yml + empty? ? '' : YAML.dump(Hash[*to_a.flatten]) + end + end + end +end diff --git a/lib/i18n/missing_translations/version.rb b/lib/i18n/missing_translations/version.rb new file mode 100644 index 0000000..1478369 --- /dev/null +++ b/lib/i18n/missing_translations/version.rb @@ -0,0 +1,5 @@ +module I18n + class MissingTranslations + VERSION = "0.0.1" + end +end diff --git a/test/missing_translations_test.rb b/test/missing_translations_test.rb new file mode 100644 index 0000000..d526771 --- /dev/null +++ b/test/missing_translations_test.rb @@ -0,0 +1,45 @@ +require File.expand_path('../test_helper', __FILE__) + +module AdvaCoreTests + class I18nMissingTranslationsLogTest < Test::Unit::TestCase + attr_reader :filename + + def setup + @filename = '/tmp/test_missing_translations.log' + FileUtils.mkdir_p(File.dirname(filename)) + end + + def teardown + File.rm(filename) rescue nil + I18n.missing_translations.clear + end + + test 'logs to a memory hash' do + log = I18n::MissingTranslations::Log.new + log.log([:missing_translations, :foo]) + log.log([:missing_translations, :bar, :baz, :boz]) + log.log([:missing_translations, :bar, :baz, :buz]) + + expected = { 'missing_translations' => { 'foo' => 'Foo', 'bar' => { 'baz' => { 'boz' => 'Boz', 'buz' => 'Buz' } } } } + assert_equal expected, log + end + + test 'dumps memory log as a yaml hash' do + log = I18n::MissingTranslations::Log.new + log.log([:missing_translations, :foo, :bar]) + log.dump(out = StringIO.new) + + expected = '--- missing_translations: foo: bar: Bar ' + assert_equal expected, out.string.gsub("\n", ' ') + end + + test 'works as a rack middleware' do + File.open(filename, 'w+') { |f| f.write(YAML.dump('en' => { 'foo' => 'Foo' })) } + middleware = I18n::MissingTranslations.new(lambda { |*| I18n.t(:missing) }, filename) + middleware.call({}) + assert_equal({ 'en' => { 'foo' => 'Foo', 'missing' => 'Missing' }}, YAML.load_file(filename)) + end + end +end + + diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..87ef791 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,7 @@ +require 'rubygems' +require 'test/unit' +require 'bundler/setup' +require 'test_declarative' + +$: << File.expand_path('../../lib', __FILE__) +require 'i18n/missing_translations'