diff --git a/Gemfile b/Gemfile index e47403546..fd8184894 100644 --- a/Gemfile +++ b/Gemfile @@ -127,4 +127,5 @@ group :development, :test do gem 'coveralls', require: false # coverage analysis gem 'capybara' # integration tests gem 'poltergeist', '~> 1.5.1' # for headless JS testing + gem 'i18n-tasks' # adds tests for finding missing and unused translations end diff --git a/Gemfile.lock b/Gemfile.lock index 7829a34de..d8ccbfcb2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -110,6 +110,10 @@ GEM warden (~> 1.2.3) diff-lcs (1.1.3) docile (1.1.5) + easy_translate (0.5.0) + json + thread + thread_safe erubis (2.7.0) execjs (2.2.1) factory_girl (4.4.0) @@ -138,11 +142,21 @@ GEM haml (>= 3.1, < 4.1) railties (>= 3.1, < 4.1) hashie (3.3.1) + highline (1.6.21) hike (1.2.3) httparty (0.11.0) multi_json (~> 1.0) multi_xml (>= 0.5.2) i18n (0.6.1) + i18n-tasks (0.7.6) + activesupport + easy_translate (>= 0.5.0) + erubis + highline + i18n + slop (>= 3.5.0) + term-ansicolor + terminal-table journey (1.0.4) jquery-rails (3.1.1) railties (>= 3.0, < 5.0) @@ -257,6 +271,7 @@ GEM multi_json simplecov-html (~> 0.8.0) simplecov-html (0.8.0) + slop (3.6.0) sprockets (2.2.2) hike (~> 1.2) multi_json (~> 1.0) @@ -266,10 +281,12 @@ GEM sprockets (>= 1.0.2) term-ansicolor (1.3.0) tins (~> 1.0) + terminal-table (1.4.5) therubyracer (0.12.1) libv8 (~> 3.16.14.0) ref thor (0.19.1) + thread (0.1.4) thread_safe (0.3.4) tilt (1.4.1) tins (1.3.2) @@ -325,6 +342,7 @@ DEPENDENCIES gravatar-ultimate haml haml-rails + i18n-tasks jquery-rails jquery-ui-rails js-routes diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml new file mode 100644 index 000000000..e1a1c35d9 --- /dev/null +++ b/config/i18n-tasks.yml @@ -0,0 +1,90 @@ +# i18n-tasks finds and manages missing and unused translations https://github.com/glebm/i18n-tasks + +base_locale: en +## i18n-tasks detects locales automatically from the existing locale files +## uncomment to set locales explicitly +# locales: [en, es, fr] + +## i18n-tasks report locale, default: en, available: en, ru +# internal_locale: ru + +# Read and write locale data +data: + ## by default, translation data are read from the file system, or you can provide a custom data adapter + # adapter: I18n::Tasks::Data::FileSystem + + # Locale files to read from + read: + - config/locales/%{locale}.yml + # - config/locales/*.%{locale}.yml + # - config/locales/**/*.%{locale}.yml + + # key => file routes, matched top to bottom + write: + ## E.g., write devise and simple form keys to their respective files + # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml'] + # Catch-all + - config/locales/%{locale}.yml + # `i18n-tasks normalize -p` will force move the keys according to these rules + + # YAML / JSON serializer options, passed to load / dump / parse / serialize + yaml: + write: + # do not wrap lines at 80 characters + line_width: -1 + json: + write: + # pretty print JSON + indent: ' ' + space: ' ' + object_nl: "\n" + array_nl: "\n" + +# Find translate calls +search: + ## Default scanner finds t() and I18n.t() calls + # scanner: I18n::Tasks::Scanners::PatternWithScopeScanner + + ## Paths to search in, passed to File.find + paths: + - app/ + + ## Root for resolving relative keys (default) + # relative_roots: + # - app/views + + ## File.fnmatch patterns to exclude from search (default) + # exclude: ["*.jpg", "*.png", "*.gif", "*.svg", "*.ico", "*.eot", "*.ttf", "*.woff", "*.pdf"] + + ## Or, File.fnmatch patterns to include + # include: ["*.rb", "*.html.slim"] + + ## Lines starting with # or / are ignored by default + # ignore_lines: + # - "^\\s*[#/](?!\\si18n-tasks-use)" + +## Google Translate +# translation: +# # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate +# api_key: "AbC-dEf5" + +## Consider these keys not missing +# ignore_missing: +# - pagination.views.* + +## Consider these keys used +# ignore_unused: +# - 'simple_form.{yes,no}' +# - 'simple_form.{placeholders,hints,labels}.*' +# - 'simple_form.{error_notification,required}.:' + +## Exclude these keys from `i18n-tasks eq-base' report +# ignore_eq_base: +# all: +# - common.ok +# fr,es: +# - common.brand + +## Exclude these keys from all of the reports +# ignore: +# - kaminari.* diff --git a/config/initializers/locale.rb b/config/initializers/locale.rb index eb4ed56e7..21c2733cb 100644 --- a/config/initializers/locale.rb +++ b/config/initializers/locale.rb @@ -1,4 +1,5 @@ I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}')] +I18n.default_locale = :en if Rails.env.development? || Rails.env.test? I18n.exception_handler = lambda do |exception, locale, key, options| diff --git a/config/routes.rb b/config/routes.rb index 01600b7ed..360ed2477 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,81 +1,78 @@ Growstuff::Application.routes.draw do - get "/:locale" => 'home#index' + resources :plant_parts + + + devise_for :members, :controllers => { :registrations => "registrations", :passwords => "passwords" } + resources :members + + resources :photos + + resources :authentications + + resources :plantings + match '/plantings/owner/:owner' => 'plantings#index', :as => 'plantings_by_owner' + + resources :gardens + match '/gardens/owner/:owner' => 'gardens#index', :as => 'gardens_by_owner' + + resources :seeds + match '/seeds/owner/:owner' => 'seeds#index', :as => 'seeds_by_owner' + + resources :harvests + match '/harvests/owner/:owner' => 'harvests#index', :as => 'harvests_by_owner' + + resources :posts + match '/posts/author/:author' => 'posts#index', :as => 'posts_by_author' + + resources :scientific_names + + match 'crops/wrangle' => 'crops#wrangle', :as => 'wrangle_crops' + match 'crops/hierarchy' => 'crops#hierarchy', :as => 'crops_hierarchy' + match 'crops/search' => 'crops#search', :as => 'crops_search' + resources :crops + + resources :comments + resources :roles + resources :forums + resources :notifications + + get '/places' => 'places#index' + get '/places/search' => 'places#search', :as => 'search_places' + get '/places/:place' => 'places#show', :as => 'place' + + # everything for paid accounts etc + resources :account_types + resources :accounts + resources :orders + match 'orders/:id/checkout' => 'orders#checkout', :as => 'checkout_order' + match 'orders/:id/complete' => 'orders#complete', :as => 'complete_order' + match 'orders/:id/cancel' => 'orders#cancel', :as => 'cancel_order' + + resources :order_items + resources :products + + get "home/index" root :to => 'home#index' - scope '/:locale' do - - resources :plant_parts - - devise_for :members, :controllers => { :registrations => "registrations", :passwords => "passwords" } - resources :members - - resources :photos - - resources :authentications - - resources :plantings - match '/plantings/owner/:owner' => 'plantings#index', :as => 'plantings_by_owner' - - resources :gardens - match '/gardens/owner/:owner' => 'gardens#index', :as => 'gardens_by_owner' - - resources :seeds - match '/seeds/owner/:owner' => 'seeds#index', :as => 'seeds_by_owner' - - resources :harvests - match '/harvests/owner/:owner' => 'harvests#index', :as => 'harvests_by_owner' - - resources :posts - match '/posts/author/:author' => 'posts#index', :as => 'posts_by_author' - - resources :scientific_names - - match 'crops/wrangle' => 'crops#wrangle', :as => 'wrangle_crops' - match 'crops/hierarchy' => 'crops#hierarchy', :as => 'crops_hierarchy' - match 'crops/search' => 'crops#search', :as => 'crops_search' - resources :crops - - resources :comments - resources :roles - resources :forums - resources :notifications - - get '/places' => 'places#index' - get '/places/search' => 'places#search', :as => 'search_places' - get '/places/:place' => 'places#show', :as => 'place' - - # everything for paid accounts etc - resources :account_types - resources :accounts - resources :orders - match 'orders/:id/checkout' => 'orders#checkout', :as => 'checkout_order' - match 'orders/:id/complete' => 'orders#complete', :as => 'complete_order' - match 'orders/:id/cancel' => 'orders#cancel', :as => 'cancel_order' - - resources :order_items - resources :products - - match 'auth/:provider/callback' => 'authentications#create' + match 'auth/:provider/callback' => 'authentications#create' - match '/policy/:action' => 'policy#:action' + match '/policy/:action' => 'policy#:action' - match '/support' => 'support#index' - match '/support/:action' => 'support#:action' + match '/support' => 'support#index' + match '/support/:action' => 'support#:action' - match '/about' => 'about#index' - match '/about/:action' => 'about#:action' + match '/about' => 'about#index' + match '/about/:action' => 'about#:action' - match '/shop' => 'shop#index' - match '/shop/:action' => 'shop#:action' + match '/shop' => 'shop#index' + match '/shop/:action' => 'shop#:action' - match '/admin/orders' => 'admin/orders#index' - match '/admin/orders/:action' => 'admin/orders#:action' - match '/admin' => 'admin#index' - match '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter - match '/admin/:action' => 'admin#:action' + match '/admin/orders' => 'admin/orders#index' + match '/admin/orders/:action' => 'admin/orders#:action' + match '/admin' => 'admin#index' + match '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter + match '/admin/:action' => 'admin#:action' - end - -end \ No newline at end of file +end diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb new file mode 100644 index 000000000..0475c9fcc --- /dev/null +++ b/spec/i18n_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' +require 'i18n/tasks' + +describe 'I18n' do + let(:i18n) { I18n::Tasks::BaseTask.new } + let(:missing_keys) { i18n.missing_keys } + let(:unused_keys) { i18n.unused_keys } + + it 'does not have missing keys' do + expect(missing_keys).to be_empty, + "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them" + end + + it 'does not have unused keys' do + expect(i18n.unused_keys).to be_empty, + "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them" + end +end