From 84810034946c085f95051a167c0f3de724258eed Mon Sep 17 00:00:00 2001 From: Keita Kobayashi Date: Fri, 20 Nov 2015 14:57:46 +0900 Subject: [PATCH] Load locales from I18n.available_locales Also uses a Railtie to load i18n files instead of the engine (I was having some trouble with the Engine loading the files at all with Rails 4.2.x). Pulls code from [devise-i18n](https://github.com/tigrish/devise-i18n). [closes #8] --- Gemfile.lock | 52 ++++++++++++++++++++++ doorkeeper-i18n.gemspec | 1 + lib/doorkeeper-i18n.rb | 5 +-- lib/doorkeeper-i18n/railtie.rb | 26 +++++++++++ log/development.log | 0 {config => rails}/locales/en.yml | 0 {config => rails}/locales/es.yml | 0 {config => rails}/locales/fr.yml | 0 {config => rails}/locales/it.yml | 0 {config => rails}/locales/ja.yml | 0 {config => rails}/locales/pt-BR.yml | 0 {config => rails}/locales/zh-CN.yml | 0 {config => rails}/locales/zh-TW.yml | 0 spec/doorkeeper-i18n_spec.rb | 4 +- spec/locale_loading_spec.rb | 68 +++++++++++++++++++++++++++++ spec/spec_helper.rb | 2 + spec/support/fake_app.rb | 45 +++++++++++++++++++ 17 files changed, 197 insertions(+), 6 deletions(-) create mode 100644 lib/doorkeeper-i18n/railtie.rb create mode 100644 log/development.log rename {config => rails}/locales/en.yml (100%) rename {config => rails}/locales/es.yml (100%) rename {config => rails}/locales/fr.yml (100%) rename {config => rails}/locales/it.yml (100%) rename {config => rails}/locales/ja.yml (100%) rename {config => rails}/locales/pt-BR.yml (100%) rename {config => rails}/locales/zh-CN.yml (100%) rename {config => rails}/locales/zh-TW.yml (100%) create mode 100644 spec/locale_loading_spec.rb create mode 100644 spec/support/fake_app.rb diff --git a/Gemfile.lock b/Gemfile.lock index 2d19b33..f92198f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,12 +6,56 @@ PATH GEM remote: http://rubygems.org/ specs: + actionpack (4.2.5) + actionview (= 4.2.5) + activesupport (= 4.2.5) + rack (~> 1.6) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.5) + activesupport (= 4.2.5) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activesupport (4.2.5) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + builder (3.2.2) diff-lcs (1.2.5) + erubis (2.7.0) i18n (0.7.0) i18n-spec (0.6.0) iso iso (0.2.1) i18n + json (1.8.3) + loofah (2.0.3) + nokogiri (>= 1.5.9) + mini_portile (0.6.2) + minitest (5.8.3) + nokogiri (1.6.6.4) + mini_portile (~> 0.6.0) + rack (1.6.4) + rack-test (0.6.3) + rack (>= 1.0) + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.7) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.2) + loofah (~> 2.0) + railties (4.2.5) + actionpack (= 4.2.5) + activesupport (= 4.2.5) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) rake (10.4.2) rspec (3.2.0) rspec-core (~> 3.2.0) @@ -26,6 +70,10 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.2.0) rspec-support (3.2.2) + thor (0.19.1) + thread_safe (0.3.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) PLATFORMS ruby @@ -33,5 +81,9 @@ PLATFORMS DEPENDENCIES doorkeeper-i18n! i18n-spec (~> 0.6.0) + railties rake rspec + +BUNDLED WITH + 1.10.6 diff --git a/doorkeeper-i18n.gemspec b/doorkeeper-i18n.gemspec index 28c70d4..9355033 100644 --- a/doorkeeper-i18n.gemspec +++ b/doorkeeper-i18n.gemspec @@ -17,4 +17,5 @@ Gem::Specification.new do |s| s.add_development_dependency "rake" s.add_development_dependency "rspec" s.add_development_dependency "i18n-spec", "~> 0.6.0" + s.add_development_dependency "railties", ">= 0" end diff --git a/lib/doorkeeper-i18n.rb b/lib/doorkeeper-i18n.rb index 692fb48..cff6c1e 100644 --- a/lib/doorkeeper-i18n.rb +++ b/lib/doorkeeper-i18n.rb @@ -1,4 +1 @@ -module DoorkeeperI18n - class Engine < ::Rails::Engine - end -end +require 'doorkeeper-i18n/railtie' if defined?(Rails) diff --git a/lib/doorkeeper-i18n/railtie.rb b/lib/doorkeeper-i18n/railtie.rb new file mode 100644 index 0000000..2d2c585 --- /dev/null +++ b/lib/doorkeeper-i18n/railtie.rb @@ -0,0 +1,26 @@ +require 'rails' + +module DoorkeeperI18n + class Railtie < ::Rails::Railtie #:nodoc: + initializer 'doorkeeper-i18n' do |app| + DoorkeeperI18n::Railtie.instance_eval do + pattern = pattern_from app.config.i18n.available_locales + + add("rails/locales/#{pattern}.yml") + end + end + + protected + + def self.add(pattern) + files = Dir[File.join(File.dirname(__FILE__), '../..', pattern)] + + I18n.load_path.concat(files) + end + + def self.pattern_from(args) + array = Array(args || []) + array.blank? ? '*' : "{#{array.join ','}}" + end + end +end diff --git a/log/development.log b/log/development.log new file mode 100644 index 0000000..e69de29 diff --git a/config/locales/en.yml b/rails/locales/en.yml similarity index 100% rename from config/locales/en.yml rename to rails/locales/en.yml diff --git a/config/locales/es.yml b/rails/locales/es.yml similarity index 100% rename from config/locales/es.yml rename to rails/locales/es.yml diff --git a/config/locales/fr.yml b/rails/locales/fr.yml similarity index 100% rename from config/locales/fr.yml rename to rails/locales/fr.yml diff --git a/config/locales/it.yml b/rails/locales/it.yml similarity index 100% rename from config/locales/it.yml rename to rails/locales/it.yml diff --git a/config/locales/ja.yml b/rails/locales/ja.yml similarity index 100% rename from config/locales/ja.yml rename to rails/locales/ja.yml diff --git a/config/locales/pt-BR.yml b/rails/locales/pt-BR.yml similarity index 100% rename from config/locales/pt-BR.yml rename to rails/locales/pt-BR.yml diff --git a/config/locales/zh-CN.yml b/rails/locales/zh-CN.yml similarity index 100% rename from config/locales/zh-CN.yml rename to rails/locales/zh-CN.yml diff --git a/config/locales/zh-TW.yml b/rails/locales/zh-TW.yml similarity index 100% rename from config/locales/zh-TW.yml rename to rails/locales/zh-TW.yml diff --git a/spec/doorkeeper-i18n_spec.rb b/spec/doorkeeper-i18n_spec.rb index befb47f..cbbc3fb 100644 --- a/spec/doorkeeper-i18n_spec.rb +++ b/spec/doorkeeper-i18n_spec.rb @@ -1,8 +1,8 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper') -Dir.glob('config/locales/*.yml').each do |locale_file| +Dir.glob('rails/locales/*.yml').each do |locale_file| describe "a doorkeeper-i18n #{locale_file} locale file" do it_behaves_like 'a valid locale file', locale_file - it { expect(locale_file).to be_a_subset_of 'config/locales/en.yml' } + it { expect(locale_file).to be_a_subset_of 'rails/locales/en.yml' } end end diff --git a/spec/locale_loading_spec.rb b/spec/locale_loading_spec.rb new file mode 100644 index 0000000..7cb7a6a --- /dev/null +++ b/spec/locale_loading_spec.rb @@ -0,0 +1,68 @@ +# encoding: utf-8 +require File.expand_path(File.dirname(__FILE__) + '/spec_helper') + +describe 'Locale loading' do + let(:app) do + DoorkeeperI18n::Spec::FakeApp + end + + let(:translate_stuff) do + lambda do + <<-EOS.gsub(/^ */, '') + In French: #{I18n.t('doorkeeper.layouts.admin.nav.oauth2_provider', locale: :fr)} + In Italian: #{I18n.t('doorkeeper.layouts.admin.nav.oauth2_provider', locale: :it)} + In Japanese: #{I18n.t('doorkeeper.layouts.admin.nav.oauth2_provider', locale: :ja)} + EOS + end + end + + context 'when i18n.available_locales are specified in config' do + let(:translations) do + app.run(translate_stuff) do |config| + config.i18n.available_locales = [:fr, :it] + end + end + + it 'loads only specified locales' do + expected_translations = <<-EOS.gsub(/^ */, '') + In French: Fournisseur OAuth2 + In Italian: OAuth2 Provider + In Japanese: translation missing: ja.doorkeeper.layouts.admin.nav.oauth2_provider + EOS + + expect(translations).to eq(expected_translations) + end + end + + context 'when single locale is assigned to i18n.available_locales' do + let(:translations) do + app.run(translate_stuff) do |config| + config.i18n.available_locales = 'fr' + end + end + + it 'loads only this locale' do + expected_translations = <<-EOS.gsub(/^ */, '') + In French: Fournisseur OAuth2 + In Italian: translation missing: it.doorkeeper.layouts.admin.nav.oauth2_provider + In Japanese: translation missing: ja.doorkeeper.layouts.admin.nav.oauth2_provider + EOS + + expect(translations).to eq(expected_translations) + end + end + + context 'when i18n.available_locales is not set' do + let(:translations) { app.run(translate_stuff) } + + it 'loads all locales' do + expected_translations = <<-EOS.gsub(/^ */, '') + In French: Fournisseur OAuth2 + In Italian: OAuth2 Provider + In Japanese: OAuth2 プロバイダー + EOS + + expect(translations).to eq(expected_translations) + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f31596a..4883f1d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,3 +3,5 @@ require "rspec" require "i18n-spec" + +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f} diff --git a/spec/support/fake_app.rb b/spec/support/fake_app.rb new file mode 100644 index 0000000..e04f630 --- /dev/null +++ b/spec/support/fake_app.rb @@ -0,0 +1,45 @@ +module DoorkeeperI18n + module Spec + module FakeApp + # + # Starts a new Rails app and runs the given config block before + # initializing it + # + def self.start + require 'action_controller/railtie' + require 'doorkeeper-i18n' + + app = Class.new(Rails::Application) + app.config.eager_load = false + app.config.i18n.enforce_available_locales = false + + yield(app.config) if block_given? + + app.initialize! + end + + # + # Initialize Rails app in a clean environment. + # + # @param test [Proc] which have to be run after app is initialized + # @return [String] Result of calling +test+ after app was initialized + # + def self.run(test, &block) + r, w = IO.pipe + + pid = fork do + r.close + + start(&block) + + w.write(test.call) + end + + w.close + result = r.read + Process.wait(pid) + result + end + end + end +end