Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uk/1562 add i18n js gem #1564

Merged
merged 11 commits into from Aug 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -4,6 +4,7 @@ ruby "2.1.5"
gem 'rails', '3.2.21'
gem 'rails-i18n', '~> 3.0.0'
gem 'i18n', '~> 0.6.11'
gem 'i18n-js', '~> 3.0.0'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a gem can be in a single commit.


# Patched version. See http://rubysec.com/advisories/CVE-2015-5312/.
gem 'nokogiri', '>= 1.6.7.1'
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Expand Up @@ -417,6 +417,8 @@ GEM
multi_json (~> 1.0)
multi_xml
i18n (0.6.11)
i18n-js (3.0.0)
i18n (~> 0.6, >= 0.6.6)
immigrant (0.1.6)
activerecord (>= 3.0)
foreigner (>= 1.2.1)
Expand Down Expand Up @@ -704,6 +706,7 @@ DEPENDENCIES
guard-rspec
haml
i18n (~> 0.6.11)
i18n-js (~> 3.0.0)
immigrant
jquery-migrate-rails
jquery-rails
Expand Down
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -108,6 +108,9 @@ If you want karma to automatically rerun the tests on file modification, use:

./script/karma start

### Multilingual
Do not forget to run `rake tmp:cache:clear` after locales are updated to reload I18n js translations.

## Credits

* Andrew Spinks (http://github.com/andrewspinks)
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/admin/all.js
Expand Up @@ -48,7 +48,7 @@
//= require textAngular-rangy.min.js
//= require textAngular-sanitize.min.js
//= require textAngular.min.js
//= require darkswarm/i18n.js
//= require i18n/translations
//= require darkswarm/i18n.translate.js


Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/darkswarm/all.js.coffee
Expand Up @@ -16,7 +16,7 @@
#= require ../shared/angular-local-storage.js
#= require ../shared/angular-slideables.js
#= require angularjs-file-upload

#= require i18n/translations

#= require angular-rails-templates
#= require_tree ../templates
Expand Down
9 changes: 0 additions & 9 deletions app/assets/javascripts/darkswarm/i18n.js.erb

This file was deleted.

14 changes: 4 additions & 10 deletions app/assets/javascripts/darkswarm/i18n.translate.js.coffee
@@ -1,17 +1,11 @@
# Old aliases before i18n-js was introduced.
# TODO - delete it after everything is moved to i18n-js

# Declares the translation function t.
# You can use translate('login') or t('login') in Javascript.
window.translate = (key, options = {}) ->
unless 'I18n' of window
console.log 'The I18n object is undefined. Cannot translate text.'
return key
dict = I18n
parts = key.split '.'
while (parts.length)
part = parts.shift()
return key unless part of dict
dict = dict[part]
text = dict
for name, value of options
text = text.split("%{#{name}}").join(value)
text
I18n.t(key, options)
window.t = window.translate
3 changes: 2 additions & 1 deletion app/controllers/base_controller.rb
Expand Up @@ -8,6 +8,7 @@ class BaseController < ApplicationController
include Spree::Core::ControllerHelpers::Order
include Spree::Core::ControllerHelpers::RespondWith

include I18nHelper
include EnterprisesHelper
include OrderCyclesHelper

Expand All @@ -17,9 +18,9 @@ class BaseController < ApplicationController
# include Spree::ProductsHelper so that method is available on the controller
include Spree::ProductsHelper

before_filter :set_locale
before_filter :check_order_cycle_expiry


private

def set_order_cycles
Expand Down
3 changes: 3 additions & 0 deletions app/controllers/spree/admin/base_controller_decorator.rb
@@ -1,6 +1,9 @@
require 'spree/core/controller_helpers/respond_with_decorator'

Spree::Admin::BaseController.class_eval do
include I18nHelper

before_filter :set_locale
before_filter :warn_invalid_order_cycles

# Warn the user when they have an active order cycle with hubs that are not ready
Expand Down
7 changes: 7 additions & 0 deletions app/helpers/i18n_helper.rb
@@ -0,0 +1,7 @@
module I18nHelper
private

def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
end
@@ -0,0 +1,3 @@
/ insert_before "div#wrapper"

= render "layouts/i18n_script"
4 changes: 4 additions & 0 deletions app/views/layouts/_i18n_script.html.haml
@@ -0,0 +1,4 @@
%script
I18n.default_locale = "#{I18n.default_locale}";
I18n.locale = "#{I18n.locale}";
I18n.fallbacks = "default_locale";
2 changes: 1 addition & 1 deletion app/views/layouts/darkswarm.html.haml
Expand Up @@ -17,7 +17,7 @@
= split_stylesheet_link_tag "darkswarm/all"
= javascript_include_tag "darkswarm/all"


= render "layouts/i18n_script"
= render "layouts/bugherd_script"
= csrf_meta_tags

Expand Down
3 changes: 2 additions & 1 deletion config/application.rb
Expand Up @@ -70,7 +70,8 @@ class Application < Rails::Application

# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = ENV["LOCALE"]
config.i18n.default_locale = ENV["LOCALE"] || ENV["I18N_LOCALE"] || "en"
config.i18n.available_locales = ENV["AVAILABLE_LOCALES"].andand.split(',').andand.map(&:strip) || [config.i18n.default_locale]
I18n.locale = config.i18n.locale = config.i18n.default_locale

# Setting this to true causes a performance regression in Rails 3.2.17
Expand Down
2 changes: 2 additions & 0 deletions config/application.yml.example
Expand Up @@ -9,6 +9,8 @@ TIMEZONE: Melbourne
DEFAULT_COUNTRY_CODE: AU
# Locale for translation.
LOCALE: en
# For multilingual - ENV doesn't have array so pass it as string with commas
AVAILABLE_LOCALES: en,es,en-GB
# Spree zone.
CHECKOUT_ZONE: Australia
# Find currency codes at http://en.wikipedia.org/wiki/ISO_4217.
Expand Down
1 change: 1 addition & 0 deletions config/environments/test.rb
Expand Up @@ -35,6 +35,7 @@

# Tests assume English text on the site.
config.i18n.default_locale = "en"
config.i18n.available_locales = ['en', 'es']
I18n.locale = config.i18n.locale = config.i18n.default_locale

# Use SQL instead of Active Record's schema dumper when creating the test database.
Expand Down
30 changes: 30 additions & 0 deletions config/initializers/i18n-js.rb
@@ -0,0 +1,30 @@
# This is copied from https://github.com/fnando/i18n-js/blob/master/lib/i18n/js.rb
# As in spree core en.yml there are translations -
# en:
# no: "No"
# yes: "Yes"
# Which become to true and false and those have no #to_sym method
# TODO - remove this after spree core locales are fixed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great. This way it will be super easy to see what needs to be changed after the Spree upgrade.


module I18n
module JS
# Filter translations according to the specified scope.
def self.filter(translations, scopes)
scopes = scopes.split(".") if scopes.is_a?(String)
scopes = scopes.clone
scope = scopes.shift
if scope == "*"
results = {}
translations.each do |scope, translations|
tmp = scopes.empty? ? translations : filter(translations, scopes)
scope_symbol = scope.respond_to?(:to_sym) ? scope.to_sym : scope.to_s.to_sym
results[scope_symbol] = tmp unless tmp.nil?
end
return results
elsif translations.respond_to?(:key?) && translations.key?(scope.to_sym)
return {scope.to_sym => scopes.empty? ? translations[scope.to_sym] : filter(translations[scope.to_sym], scopes)}
end
nil
end
end
end
10 changes: 4 additions & 6 deletions lib/tasks/karma.rake
Expand Up @@ -39,11 +39,9 @@ namespace :karma do
end

def i18n_file
I18n.backend.send(:init_translations) unless I18n.backend.initialized?
f = Tempfile.open('i18n.js', Rails.root.join('tmp') )
f.write 'window.I18n = '
f.write I18n.backend.send(:translations)[I18n.locale].with_indifferent_access.to_json.html_safe
f.flush
f.path
raise "I18n::JS module is missing" unless defined?(I18n::JS)
I18n::JS::DEFAULT_EXPORT_DIR_PATH.replace('tmp/javascripts')
I18n::JS.export
"#{Rails.root.join(I18n::JS::DEFAULT_EXPORT_DIR_PATH)}/translations.js"
end
end
40 changes: 40 additions & 0 deletions spec/features/admin/multilingual_spec.rb
@@ -0,0 +1,40 @@
require 'spec_helper'

feature 'Multilingual', js: true do
include AuthenticationWorkflow
include WebHelper

background do
login_to_admin_section
end

it 'has two locales available' do
expect(Rails.application.config.i18n[:default_locale]).to eq 'en'
expect(Rails.application.config.i18n[:locale]).to eq 'en'
expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es']
end

it 'can switch language by params' do
expect(get_i18n_locale).to eq 'en'
expect(get_i18n_translation('spree_admin_overview_enterprises_header')).to eq 'My Enterprises'
expect(page).to have_content 'My Enterprises'

visit spree.admin_path(locale: 'es')
expect(get_i18n_locale).to eq 'es'
expect(get_i18n_translation('spree_admin_overview_enterprises_header')).to eq 'Mis Organizaciones'
expect(page).to have_content 'Mis Organizaciones'
end

it 'fallbacks to default_locale' do
pending 'current spree core has a bug if not available locale is provided'
# undefined method `delete_if' for "translation missing: it.date.month_names":String
# inside core/app/views/spree/admin/shared/_translations.html.erb

# I18n-js fallsback to 'en'
visit spree.admin_path(locale: 'it')
expect(get_i18n_locale).to eq 'it'
expect(get_i18n_translation('spree_admin_overview_enterprises_header')).to eq 'My Enterprises'
# This still is italian until we change enforce_available_locales to `true`
expect(page).to have_content 'Le Mie Aziende'
end
end
32 changes: 32 additions & 0 deletions spec/features/consumer/multilingual_spec.rb
@@ -0,0 +1,32 @@
require 'spec_helper'

feature 'Multilingual', js: true do
include WebHelper

it 'has two locales available' do
expect(Rails.application.config.i18n[:default_locale]).to eq 'en'
expect(Rails.application.config.i18n[:locale]).to eq 'en'
expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es']
end

it 'can switch language by params' do
visit root_path
expect(get_i18n_locale).to eq 'en'
expect(get_i18n_translation('label_shops')).to eq 'Shops'
expect(page).to have_content 'Interested in getting on the Open Food Network?'
expect(page).to have_content 'SHOPS'

visit root_path(locale: 'es')
expect(get_i18n_locale).to eq 'es'
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
expect(page).to have_content '¿Estás interesada en entrar en Open Food Network?'
expect(page).to have_content 'TIENDAS'

# I18n-js fallsback to 'en'
visit root_path(locale: 'it')
expect(get_i18n_locale).to eq 'it'
expect(get_i18n_translation('label_shops')).to eq 'Shops'
# This still is italian until we change enforce_available_locales to `true`
expect(page).to have_content 'NEGOZI'
end
end
1 change: 1 addition & 0 deletions spec/javascripts/application_spec.js
Expand Up @@ -13,6 +13,7 @@
//= require textAngular-sanitize.min.js
//= require textAngular.min.js
//= require moment
//= require i18n
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change related to Karma? If not, I'd suggest moving this change to a separate commit. But see above for comments about treating this as a spike.


angular.module('templates', [])
angular.module('google-maps', []);
Expand Down
8 changes: 8 additions & 0 deletions spec/support/request/web_helper.rb
Expand Up @@ -113,6 +113,14 @@ def dirty_form_dialog
DirtyFormDialog.new(page)
end

def get_i18n_locale
page.evaluate_script("I18n.locale;")
end

def get_i18n_translation(key = nil)
page.evaluate_script("I18n.t('#{key}');")
end

# Fetch the content of a script block
# eg. script_content with: 'my-script.com'
# Returns nil if not found
Expand Down