Merge pull request #417 from tygriffin/I18n

I18n
This commit is contained in:
pozorvlak
2014-10-18 11:11:25 +01:00
18 changed files with 352 additions and 92 deletions

View File

@@ -45,4 +45,5 @@ submit the change with your pull request.
- Marlena Compton / [Marlena](https://github.com/marlena)
- Elizabeth A. Kari / [catfriend](https://github.com/catfriend)
- Cheri Allen / [cherimarie](https://github.com/cherimarie)
- Maki Sugita / [macckii](https:://github.com/macckii)
- Shiho Takagi / [oshiho3](https://github.com/oshiho3)

View File

@@ -131,4 +131,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

View File

@@ -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)
@@ -272,10 +286,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)
@@ -331,6 +347,7 @@ DEPENDENCIES
gravatar-ultimate
haml
haml-rails
i18n-tasks
jquery-rails
jquery-ui-rails
js-routes

View File

@@ -4,6 +4,7 @@ class ApplicationController < ActionController::Base
include ApplicationHelper
after_filter :store_location
before_filter :set_locale
def store_location
if (request.path != "/members/sign_in" &&
@@ -32,5 +33,14 @@ class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied do |exception|
redirect_to request.referer || root_url, :alert => exception.message
end
def set_locale
I18n.locale = params[:locale] || extract_locale_from_subdomain || I18n.default_locale
end
def extract_locale_from_subdomain
parsed_locale = request.subdomains.first
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
end

View File

@@ -4,19 +4,13 @@
.row
.col-md-8.info
%p
#{ENV['GROWSTUFF_SITE_NAME']} is a community of food gardeners.
We're building an open source platform to help you learn about
growing food, track what you plant and harvest, and swap
seeds and produce with other gardeners near you.
%p= t('.intro', site_name: ENV['GROWSTUFF_SITE_NAME'])
= render :partial => 'stats'
.col-md-4.signup
%p Join now for your free garden journal, seed sharing, forums, and more.
%p= link_to 'Sign up', new_member_registration_path, :class => 'btn btn-primary btn-lg'
%p= t('.perks')
%p= link_to(t('.sign_up'), new_member_registration_path, :class => 'btn btn-primary btn-lg')
%p
%small
Or
= link_to "sign in", new_member_session_path
if you already have an account.
= t('.already_html', sign_in: link_to(t('.sign_in_linktext'), new_member_session_path))

View File

@@ -1,14 +1,14 @@
.row
.col-md-6.hidden-xs
- cache "interesting_crops", :expires_in => 1.day do
%h2 Some of our crops
%h2= t('.our_crops')
- Crop.interesting.each do |c|
.col-md-3{:style => 'margin:0px; padding: 3px'}
= render :partial => 'crops/image_with_popover', :locals => { :crop => c }
.col-md-6
- cache "interesting_plantings" do
%h2 Recently planted
%h2= t('.recently_planted')
= render :partial => 'plantings/list', :locals => { :plantings => Planting.interesting.first(4) }
.row
@@ -16,8 +16,8 @@
- cache "recent_crops" do
%p{ :style => 'margin-top: 11.25px' }
%strong
Recently added crops:
#{t('.recently_added')}:
!= Crop.recent.limit(12).map {|c| link_to(c, c) }.join(", ")
%p.text-right
=link_to "View all crops »", crops_path
=link_to "#{t('.view_all')} »", crops_path

View File

@@ -1,4 +1,4 @@
%h2 Discussion
%h2= t('.discussion')
- cache "recent_posts" do
- posts = Post.limit(6)
@@ -10,9 +10,9 @@
- if forums
%ul.list-inline
%li
%strong Forums:
%strong #{t('.forums')}:
- forums.each do |f|
%li= link_to f.name, f
%p.text-right
= link_to "View all posts »", posts_path
= link_to "#{t('.view_all')} »", posts_path

View File

@@ -1,17 +1,14 @@
%h2 Keep in touch
%h2= t('.keep_in_touch')
%p
=image_tag("twitter_32.png", :alt => '')
Follow
=link_to '@growstufforg', 'http://twitter.com/growstufforg'
on Twitter.
= t('.twitter_html', link: link_to(t('.twitter_linktext'), 'http://twitter.com/growstufforg'))
%p
=image_tag("blog_32.png", :alt => '')
Subscribe to the
=link_to 'Growstuff Blog', 'http://blog.growstuff.org/'
= t('.blog_html', link: link_to(t('.blog_linktext'), 'http://blog.growstuff.org/'))
%p
=image_tag("email_32.png", :alt => '')
Subscribe to our
=link_to 'email newsletter', 'http://blog.growstuff.org/newsletter'
= t('.newsletter_html', link: link_to(t('.newsletter_linktext'), 'http://blog.growstuff.org/newsletter'))

View File

@@ -2,7 +2,7 @@
.hidden-xs
- members = Member.interesting.first(6)
- if members.present?
%h2 Some of our members
%h2= t('.title')
.row
- members.each do |m|
@@ -10,4 +10,4 @@
= render :partial => "members/thumbnail", :locals => { :member => m }
%p.text-right
= link_to "View all members »", members_path
= link_to "#{t('.view_all')} »", members_path

View File

@@ -1,50 +1,29 @@
%h2 Open Source
%h2= t('.open_source_title')
%p
#{ENV['GROWSTUFF_SITE_NAME']} is open source software,
which means that we share this website's code for free with our
community and the world. We believe that openness,
sustainability, and social good go hand in hand. You can read more
about
=link_to "why Growstuff is open source", "http://blog.growstuff.org/2013/02/20/why-growstuff-is-open-source/"
or check out our code on
=succeed '.' do
= link_to 'Github', 'http://github.com/Growstuff/growstuff'
= t('.open_source_body_html', why: link_to(t('.why_linktext'), 'http://blog.growstuff.org/2013/02/20/why-growstuff-is-open-source/'),
github: link_to(t('.github_linktext'), 'http://github.com/Growstuff/growstuff'),
site_name: ENV['GROWSTUFF_SITE_NAME'] )
%h2 Open Data and APIs
%h2= t('.open_data_title')
%p
We're building a database
of crops, planting advice, seed sources, and other information
that anyone can use for free, under a
= succeed '.' do
= link_to 'Creative Commons license', 'http://creativecommons.org/licenses/by-sa/3.0/'
You can use this data for research, to build apps, or for any
purpose at all. Read more about our
= t('.open_data_body_html', creative_commons_link: link_to(t('.creative_commons_linktext'), 'http://creativecommons.org/licenses/by-sa/3.0/'),
wiki_link: link_to(t('.wiki_linktext'), 'http://wiki.growstuff.org/index.php/Open_data'),
api_docs_link: link_to(t('.api_docs_linktext'), 'http://wiki.growstuff.org/index.php/API'))
= link_to 'open data', 'http://wiki.growstuff.org/index.php/Open_data'
and
= succeed '.' do
= link_to 'API documentation', 'http://wiki.growstuff.org/index.php/API'
%h2 Get Involved
%h2= t('.get_involved_title')
%p
We believe in collaboration, and work closely with our members
and the wider food-growing community.
Our team includes volunteers from all walks of life
and all skill levels. To get involved, visit
= link_to 'Growstuff Talk', 'http://talk.growstuff.org/'
or find more information on the
= succeed "." do
= link_to 'Growstuff Wiki', 'http://wiki.growstuff.org/'
= t('.get_involved_body_html', talk_link: link_to(t('.talk_linktext'), 'http://talk.growstuff.org/'),
wiki_link: link_to(t('.wiki_linktext'), 'http://wiki.growstuff.org/'))
%h2 Support Growstuff
%h2= t('.support_title')
%p
Growstuff is independent,
=succeed "," do
=link_to 'ad-free', 'http://wiki.growstuff.org/index.php/Why_no_ads%3F'
and we have no outside investment. You can support our work by
=succeed "." do
=link_to 'buying a paid account', shop_path
= t('.support_body_html', ad_free: link_to(t('.ad_free_linktext'), 'http://wiki.growstuff.org/index.php/Why_no_ads%3F'),
buy_account: link_to(t('.buy_account_linktext'), shop_path))

View File

@@ -1,18 +1,18 @@
- seeds = Seed.interesting.first(6)
- if seeds.present?
%h2 Seeds available to trade
%h2= t('.title')
- cache "interesting_seeds" do
- if seeds.length > 0
%table.table.table-striped
%tr
%th Owner
%th Crop
%th.hidden-xs.hidden-sm Description
%th Will trade to
%th From location
%th= t('.owner')
%th= t('.crop')
%th.hidden-xs.hidden-sm= t('.description')
%th= t('.trade_to')
%th= t('.from')
%th
- seeds.each do |seed|
@@ -23,8 +23,8 @@
%td= seed.tradable? ? seed.tradable_to : ''
%td
- if seed.tradable?
= seed.owner.location.blank? ? "unspecified" : truncate(seed.owner.location, :length => 25, :separator => ', ')
%td= link_to 'Details', seed, :class => 'btn btn-default btn-xs'
= seed.owner.location.blank? ? t('.unspecified') : truncate(seed.owner.location, :length => 25, :separator => ', ')
%td= link_to t('.details'), seed, :class => 'btn btn-default btn-xs'
%p.text-right
= link_to "View all seeds »", seeds_path
= link_to "#{t('.view_all')} »", seeds_path

View File

@@ -1,10 +1,8 @@
- cache("homepage_stats") do
%p.stats
So far,
= link_to "#{Member.confirmed.count.to_i} members", members_path
have planted
= link_to "#{Crop.count.to_i} crops", crops_path
= link_to "#{Planting.count.to_i} times", plantings_path
in
= succeed "." do
= link_to "#{Garden.count.to_i} gardens", gardens_path
= t('.message_html', { member: link_to(t('.member_linktext', count: Member.confirmed.count.to_i), members_path),
number_crops: link_to(t('.number_crops_linktext', count: Crop.count.to_i), crops_path),
number_plantings: link_to(t('.number_plantings_linktext', count: Planting.count.to_i), plantings_path),
number_gardens: link_to(t('.number_gardens_linktext', count: Garden.count.to_i), gardens_path) })

View File

@@ -1,19 +1,16 @@
.row
.col-md-12
- if member_signed_in?
%h1
Welcome to
= succeed "," do
= ENV['GROWSTUFF_SITE_NAME']
= current_member
%h1= t('.welcome', site_name: ENV['GROWSTUFF_SITE_NAME'], member_name: current_member)
= render :partial => 'stats'
%p
.btn-group
= link_to "Plant", new_planting_path, :class => 'btn btn-default'
= link_to "Harvest", new_harvest_path, :class => 'btn btn-default'
= link_to "Add seeds", new_seed_path, :class => 'btn btn-default'
= link_to "Post", new_post_path, :class => 'btn btn-default'
= link_to "Edit profile", edit_member_registration_path, :class => 'btn btn-default'
= link_to t('.plant'), new_planting_path, :class => 'btn btn-default'
= link_to t('.harvest'), new_harvest_path, :class => 'btn btn-default'
= link_to t('.add_seeds'), new_seed_path, :class => 'btn btn-default'
= link_to t('.post'), new_post_path, :class => 'btn btn-default'
= link_to t('.edit_profile'), edit_member_registration_path, :class => 'btn btn-default'
- else
.hidden-xs

90
config/i18n-tasks.yml Normal file
View File

@@ -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.*

View File

@@ -0,0 +1,4 @@
I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}')]
I18n.default_locale = :en

View File

@@ -13,3 +13,81 @@ en:
all: "Please sign in or sign up to create a %{subject}."
manage:
all: "Not authorized to %{action} %{subject}."
home:
blurb:
intro: "%{site_name} is a community of food gardeners. We're building an open source platform to help you learn about growing food, track what you plant and harvest, and swap seeds and produce with other gardeners near you."
perks: "Join now for your free garden journal, seed sharing, forums, and more."
sign_up: "Sign up"
already_html: "Or %{sign_in} if you already have an account"
sign_in_linktext: "sign in"
crops:
our_crops: "Some of our crops"
recently_planted: "Recently planted"
recently_added: "Recently added crops"
view_all: "View all crops"
discuss:
discussion: "Discussion"
forums: "Forums"
view_all: "View all posts"
keep_in_touch:
keep_in_touch: "Keep in touch"
twitter_html: "Follow %{link} on Twitter"
twitter_linktext: "@growstufforg"
blog_html: "Subscribe to the %{link}"
blog_linktext: "Growstuff Blog"
newsletter_html: "Subscribe to our %{link}"
newsletter_linktext: "email newsletter"
members:
title: "Some of our members"
view_all: "View all members"
open:
open_source_title: "Open Source"
open_source_body_html: "%{site_name} is open source software, which means that we share this website's code for free with our community and the world. We believe that openness, sustainability, and social good go hand in hand. You can read more about %{why} or check out our code on %{github}."
why_linktext: "why Growstuff is open source"
github_linktext: "Github"
open_data_title: "Open Data and APIs"
open_data_body_html: "We're building a database of crops, planting advice, seed sources, and other information that anyone can use for free, under a %{creative_commons_link}. You can use this data for research, to build apps, or for any purpose at all. Read more about our %{wiki_link} and %{api_docs_link}."
creative_commons_linktext: "Creative Commons license"
wiki_linktext: "open data"
api_docs_linktext: "API documentation"
get_involved_title: "Get Involved"
get_involved_body_html: "We believe in collaboration, and work closely with our members and the wider food-growing community. Our team includes volunteers from all walks of life and all skill levels. To get involved, visit %{talk_link} or find more information on the %{wiki_link}."
talk_linktext: "Growstuff Talk"
wiki_linktext: "Growstuff Wiki"
support_title: "Support Growstuff"
support_body_html: "Growstuff is independent, %{ad_free} and we have no outside investment. You can support our work by %{buy_account}."
ad_free_linktext: "ad-free"
buy_account_linktext: "buying a paid account"
seeds:
title: "Seeds available to trade"
owner: "Owner"
crop: "Crop"
description: "Description"
trade_to: "Will trade to"
from: "From location"
unspecified: "unspecified"
details: "Details"
view_all: "View all seeds"
stats:
message_html: "So far, %{member} have planted %{number_crops} %{number_plantings} in %{number_gardens}."
member_linktext: "%{count} members"
number_crops_linktext: "%{count} crops"
number_plantings_linktext: "%{count} times"
number_gardens_linktext: "%{count} gardens"
index:
welcome: "Welcome to %{site_name}, %{member_name}"
plant: "Plant"
harvest: "Harvest"
add_seeds: "Add seeds"
post: "Post"
edit_profile: "Edit profile"

78
config/locales/ja.yml Normal file
View File

@@ -0,0 +1,78 @@
ja:
home:
blurb:
intro: "%{site_name}はガーデナーのコミュニティです。"
perks: "翻訳中"
sign_up: "翻訳中"
already_html: "翻訳中"
sign_in_linktext: "翻訳中"
crops:
our_crops: "翻訳中"
recently_planted: "翻訳中"
recently_added: "翻訳中"
view_all: "翻訳中"
discuss:
discussion: "翻訳中"
forums: "翻訳中"
view_all: "翻訳中"
keep_in_touch:
keep_in_touch: "翻訳中"
twitter_html: "翻訳中"
twitter_linktext: "翻訳中"
blog_html: "翻訳中"
blog_linktext: "翻訳中"
newsletter_html: "翻訳中"
newsletter_linktext: "翻訳中"
members:
title: "翻訳中"
view_all: "翻訳中"
open:
open_source_title: "翻訳中"
open_source_body_html: "翻訳中"
why_linktext: "翻訳中"
github_linktext: "翻訳中"
open_data_title: "翻訳中"
open_data_body_html: "翻訳中"
creative_commons_linktext: "翻訳中"
wiki_linktext: "翻訳中"
api_docs_linktext: "翻訳中"
get_involved_title: "翻訳中"
get_involved_body_html: "翻訳中"
talk_linktext: "翻訳中"
wiki_linktext: "翻訳中"
support_title: "翻訳中"
support_body_html: "翻訳中"
ad_free_linktext: "翻訳中"
seeds:
title: "翻訳中"
owner: "翻訳中"
crop: "翻訳中"
description: "翻訳中"
trade_to: "翻訳中"
from: "翻訳中"
unspecified: "翻訳中"
details: "翻訳中"
view_all: "翻訳中"
stats:
message_html: "翻訳中"
member_linktext: "翻訳中"
number_crops_linktext: "翻訳中"
number_plantings_linktext: "翻訳中"
number_gardens_linktext: "翻訳中"
index:
welcome: "翻訳中"
plant: "翻訳中"
harvest: "翻訳中"
add_seeds: "翻訳中"
post: "翻訳中"
edit_profile: "翻訳中"

View File

@@ -0,0 +1,16 @@
require 'spec_helper'
feature "Changing locales" do
after do
I18n.locale = :en
end
scenario "Locale can be set with a query param" do
visit "/"
expect(page).to have_content("a community of food gardeners.")
visit "/?locale=ja"
expect(page).to have_content("はガーデナーのコミュニティです。")
end
end