Merge branch '619-gender-aware-translations' of https://github.com/siefca/diaspora into siefca-619-gender-aware-translations

This commit is contained in:
Hexagon 2010-12-01 19:13:39 +01:00
commit 5651ea1d33
22 changed files with 269 additions and 43 deletions

View file

@ -30,9 +30,9 @@ class InvitationsController < Devise::InvitationsController
if e.message == "You have no invites" if e.message == "You have no invites"
flash[:error] = I18n.t 'invitations.create.no_more' flash[:error] = I18n.t 'invitations.create.no_more'
elsif e.message == "You already invited this person" elsif e.message == "You already invited this person"
flash[:error] = I18n.t 'invitations.create.already_sent' flash[:error] = I18n.t('invitations.create.already_sent', :gender => current_user)
elsif e.message == "You are already connected to this person" elsif e.message == "You are already connected to this person"
flash[:error] = I18n.t 'invitations.create.already_contacts' flash[:error] = I18n.t('invitations.create.already_contacts', :gender => current_user)
else else
raise e raise e
end end

View file

@ -55,15 +55,15 @@ class PhotosController < ApplicationController
end end
rescue TypeError rescue TypeError
message = I18n.t 'photos.create.type_error' message = I18n.t('photos.create.type_error', :gender => current_user)
respond_with :location => photos_path, :error => message respond_with :location => photos_path, :error => message
rescue CarrierWave::IntegrityError rescue CarrierWave::IntegrityError
message = I18n.t 'photos.create.integrity_error' message = I18n.t('photos.create.integrity_error', :gender => current_user)
respond_with :location => photos_path, :error => message respond_with :location => photos_path, :error => message
rescue RuntimeError => e rescue RuntimeError => e
message = I18n.t 'photos.create.runtime_error' message = I18n.t('photos.create.runtime_error', :gender => current_user)
respond_with :location => photos_path, :error => message respond_with :location => photos_path, :error => message
raise e raise e
end end

View file

@ -45,7 +45,7 @@ class RequestsController < ApplicationController
:into => aspect) :into => aspect)
if @request.save if @request.save
current_user.dispatch_request(@request) current_user.dispatch_request(@request)
flash.now[:notice] = I18n.t('requests.create.sent') flash.now[:notice] = I18n.t('requests.create.sent', :gender => current_user)
redirect_to :back redirect_to :back
else else
flash.now[:error] = @request.errors.full_messages.join(', ') flash.now[:error] = @request.errors.full_messages.join(', ')

View file

@ -28,6 +28,7 @@ class UsersController < ApplicationController
params[:user].delete(:password) if params[:user][:password].blank? params[:user].delete(:password) if params[:user][:password].blank?
params[:user].delete(:password_confirmation) if params[:user][:password].blank? and params[:user][:password_confirmation].blank? params[:user].delete(:password_confirmation) if params[:user][:password].blank? and params[:user][:password_confirmation].blank?
params[:user].delete(:language) if params[:user][:language].blank? params[:user].delete(:language) if params[:user][:language].blank?
params[:user].delete(:grammatical_gender) if params[:user][:grammatical_gender].blank?
if params[:user][:password] && params[:user][:password_confirmation] if params[:user][:password] && params[:user][:password_confirmation]
if @user.update_attributes(:password => params[:user][:password], :password_confirmation => params[:user][:password_confirmation]) if @user.update_attributes(:password => params[:user][:password], :password_confirmation => params[:user][:password_confirmation])
@ -37,7 +38,15 @@ class UsersController < ApplicationController
end end
elsif params[:user][:language] elsif params[:user][:language]
if @user.update_attributes(:language => params[:user][:language]) if @user.update_attributes(:language => params[:user][:language])
flash[:notice] = I18n.t 'users.update.language_changed' if params[:user][:grammatical_gender]
if @user.update_attributes(:grammatical_gender => params[:user][:grammatical_gender])
flash[:notice] = I18n.t 'users.update.language_changed'
else
flash[:error] = I18n.t 'users.update.language_not_changed'
end
else
flash[:notice] = I18n.t 'users.update.language_changed'
end
else else
flash[:error] = I18n.t 'users.update.language_not_changed' flash[:error] = I18n.t 'users.update.language_not_changed'
end end
@ -80,6 +89,7 @@ class UsersController < ApplicationController
@step ||= 1 @step ||= 1
if @step == 4 if @step == 4
@user.grammatical_gender = I18n::Backend::Genderize.guess(@profile.gender)
@user.getting_started = false @user.getting_started = false
@user.save @user.save
end end

View file

@ -9,7 +9,7 @@ module AspectsHelper
def remove_link( aspect ) def remove_link( aspect )
if aspect.contacts.size == 0 if aspect.contacts.size == 0
link_to I18n.t('aspects.helper.remove'), aspect, :method => :delete, :confirm => I18n.t('aspects.helper.are_you_sure') link_to I18n.t('aspects.helper.remove'), aspect, :method => :delete, :confirm => I18n.t('aspects.helper.are_you_sure', :gender => current_user)
else else
"<span class='grey' title=#{I18n.t('aspects.helper.aspect_not_empty')}>#{I18n.t('aspects.helper.remove')}</span>" "<span class='grey' title=#{I18n.t('aspects.helper.aspect_not_empty')}>#{I18n.t('aspects.helper.remove')}</span>"
end end

View file

@ -6,4 +6,30 @@ module LanguageHelper
end end
options.sort_by { |o| o[0] } options.sort_by { |o| o[0] }
end end
end
def options_for_gender_select
grammatical_gender = current_user.grammatical_gender
genders_list = I18n::Backend::Genderize.known_genders.map do |gender|
[t(".#{gender}"), gender]
end
if grammatical_gender.blank?
grammatical_gender = I18n::Backend::Genderize.guess(user.profile.gender)
end
options_for_select(genders_list, grammatical_gender.to_s)
end
def gender_select_disabled
not I18n::Backend::Genderize.supports?(current_user.language)
end
def grammatical_gender_languages
@glang_cache ||= array_or_string_for_javascript(I18n::Backend::Genderize::SupportedLanguages)
end
def options_for_grammatical_gender_block
enabled = I18n::Backend::Genderize.supports? current_user.language
{:style => 'display: ' + (enabled ? 'inline' : 'none') + ';' +
' margin-left: 1em; margin-right: 0.5em;'
}
end
end

View file

@ -22,7 +22,7 @@ module PeopleHelper
def action_link(person, is_contact) def action_link(person, is_contact)
if is_contact if is_contact
link_to t('people.profile_sidebar.remove_contact'), person, :confirm => t('are_you_sure'), :method => :delete link_to t('people.profile_sidebar.remove_contact'), person, :confirm => t('are_you_sure', :gender => current_user), :method => :delete
elsif person == current_user.person elsif person == current_user.person
link_to t('people.profile_sidebar.edit_my_profile'), edit_person_path(person) link_to t('people.profile_sidebar.edit_my_profile'), edit_person_path(person)
end end

View file

@ -29,6 +29,7 @@ class User
key :getting_started, Boolean, :default => true key :getting_started, Boolean, :default => true
key :language, String key :language, String
key :grammatical_gender, String
before_validation :strip_and_downcase_username, :on => :create before_validation :strip_and_downcase_username, :on => :create
before_validation :set_current_language, :on => :create before_validation :set_current_language, :on => :create
@ -38,6 +39,7 @@ class User
validates_format_of :username, :with => /\A[A-Za-z0-9_.]+\z/ validates_format_of :username, :with => /\A[A-Za-z0-9_.]+\z/
validates_length_of :username, :maximum => 32 validates_length_of :username, :maximum => 32
validates_inclusion_of :language, :in => AVAILABLE_LANGUAGE_CODES validates_inclusion_of :language, :in => AVAILABLE_LANGUAGE_CODES
validates_inclusion_of :grammatical_gender, :in => I18n::Backend::Genderize::known_genders + [nil]
validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?} validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?}
validates_associated :person validates_associated :person
@ -61,7 +63,7 @@ class User
person.save if person person.save if person
end end
attr_accessible :getting_started, :password, :password_confirmation, :language, attr_accessible :getting_started, :password, :password_confirmation, :language, :grammatical_gender
def strip_and_downcase_username def strip_and_downcase_username
if username.present? if username.present?

View file

@ -3,7 +3,7 @@
%h4 %h4
= t('.invite_someone_to_join') = t('.invite_someone_to_join')
%i %i
= t('.if_they_accept_info') = t('.if_they_accept_info', :gender => current_user)
%br %br
= t('.comma_seperated_plz') = t('.comma_seperated_plz')
= form_for User.new, :url => invitation_path(User) do |invite| = form_for User.new, :url => invitation_path(User) do |invite|

View file

@ -47,7 +47,7 @@
- else - else
.floating .floating
%h3 %h3
= t('.not_connected', :name => @person.name) = t('.not_connected', :name => @person.name, :gender => current_user)
- unless pending_request_for(@person) - unless pending_request_for(@person)
%h3 %h3
@ -59,5 +59,5 @@
- else - else
%h3 %h3
.description .description
= t('.already_requested', :name => @person.name) = t('.already_requested', :name => @person.name, :gender => current_user)

View file

@ -33,7 +33,7 @@
= p.text_field :caption, :value => @photo.caption = p.text_field :caption, :value => @photo.caption
= p.submit t('.update_photo') = p.submit t('.update_photo')
%p %p
= button_to t('.delete_photo'), @photo, :confirm => t('are_you_sure'), :method => :delete = button_to t('.delete_photo'), @photo, :confirm => t('are_you_sure', :gender => current_user), :method => :delete
.span-9.last .span-9.last
- if @photo.status_message_id - if @photo.status_message_id

View file

@ -24,5 +24,5 @@
= f.submit t('.update') = f.submit t('.update')
%h3 t('.cancel_my_account') %h3 t('.cancel_my_account')
%p %p
= t('.unhappy') #{link_to t('.cancel_my_account'), registration_path(resource_name), :confirm => t('are_you_sure'), :method => :delete}. = t('.unhappy') #{link_to t('.cancel_my_account'), registration_path(resource_name), :confirm => t('are_you_sure', :gender=>:neuter), :method => :delete}.
= link_to t('back'), :back = link_to t('back'), :back

View file

@ -21,7 +21,7 @@
%ul#request_result{:aspect_id => aspect_id} %ul#request_result{:aspect_id => aspect_id}
%li.error.hidden %li.error.hidden
#message #message
= link_to t('.know_email'), "#invite_user_pane", :class => "invite_user_button" = link_to t('.know_email', :gender => current_user), "#invite_user_pane", :class => "invite_user_button"
%br %br
.yo{ :style => "display:none;"} .yo{ :style => "display:none;"}
#invite_user_pane #invite_user_pane

View file

@ -23,7 +23,7 @@
- reshare_aspects = aspects_without_post(aspects, post) - reshare_aspects = aspects_without_post(aspects, post)
- unless reshare_aspects.empty? - unless reshare_aspects.empty?
= render 'shared/reshare', :aspects => reshare_aspects, :post => post = render 'shared/reshare', :aspects => reshare_aspects, :post => post
= link_to t('delete'), status_message_path(post), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete" = link_to t('delete'), status_message_path(post), :confirm => t('are_you_sure', :gender => current_user), :method => :delete, :remote => true, :class => "delete"
= render 'status_messages/status_message', :post => post, :photos => photos = render 'status_messages/status_message', :post => post, :photos => photos

View file

@ -23,6 +23,6 @@
- if current_user.owns?(post) - if current_user.owns?(post)
.right .right
= link_to t('delete'), photo_path(post), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete" = link_to t('delete'), photo_path(post), :confirm => t('are_you_sure', :gender => current_user), :method => :delete, :remote => true, :class => "delete"
/= render "comments/comments", :post => post /= render "comments/comments", :post => post

View file

@ -16,7 +16,7 @@
.time .time
= how_long_ago(@status_message) = how_long_ago(@status_message)
- if current_user.owns? @status_message - if current_user.owns? @status_message
= link_to t('.destroy'), @status_message, :confirm => t('are_you_sure'), :method => :delete = link_to t('.destroy'), @status_message, :confirm => t('are_you_sure', :gender => current_user), :method => :delete
.span-9.last .span-9.last
%h4{:style=>"margin-bottom:5px;"}= t('_comments') %h4{:style=>"margin-bottom:5px;"}= t('_comments')

View file

@ -3,13 +3,29 @@
-# the COPYRIGHT file. -# the COPYRIGHT file.
:javascript :javascript
$("#settings_nav li > a").live("click", function() { var genderized_languages = #{grammatical_gender_languages}
var target = "#"+$(this).attr('class');
if( !$(target).is(":visible") ) { $(document).ready(function(){
$(".settings_pane").fadeOut(200, function() {
$(target).delay(200).fadeIn(200); $("#settings_nav li > a").live("click", function() {
}); var target = "#"+$(this).attr('class');
} if( !$(target).is(":visible") ) {
$(".settings_pane").fadeOut(200, function() {
$(target).delay(200).fadeIn(200);
});
}
});
$("#user_language").change(function () {
var gselected = $("#user_language option:selected").val();
if ( $.inArray(gselected, genderized_languages) < 0 ) {
$("#grammatical_gender_block").hide(800);
$("#user_grammatical_gender").attr("disabled", "disabled");
} else {
$("#user_grammatical_gender").removeAttr("disabled");
$("#grammatical_gender_block").show(800);
}
});
}); });
#section_header #section_header
@ -67,6 +83,9 @@
%p %p
= f.select :language, available_language_options = f.select :language, available_language_options
%span#grammatical_gender_block{options_for_grammatical_gender_block}
= " " + t('.address_me_as')
= select_tag 'user[grammatical_gender]', options_for_gender_select, :disabled => gender_select_disabled
= f.submit t('.change_language') = f.submit t('.change_language')
%br %br
@ -83,5 +102,5 @@
%h3 %h3
= t('.close_account') = t('.close_account')
= link_to t('.close_account'), current_user, = link_to t('.close_account'), current_user,
:confirm => t('are_you_sure'), :method => :delete, :confirm => t('are_you_sure', :gender => current_user), :method => :delete,
:class => "button" :class => "button"

View file

@ -12,7 +12,7 @@
$(".aspects li").find(".delete").live("click", function(){ $(".aspects li").find(".delete").live("click", function(){
var aspectElement = $(this).parent("li"); var aspectElement = $(this).parent("li");
if (confirm("#{t('are_you_sure')}")){ if (confirm("#{t('are_you_sure', :gender => current_user)}")){
aspectElement.fadeOut(300, function(){aspectElement.remove();}); aspectElement.fadeOut(300, function(){aspectElement.remove();});
} }
}); });

View file

@ -1,3 +1,5 @@
# Encoding: utf-8
#
# Copyright (c) 2010, Diaspora Inc. This file is # Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See # licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file. # the COPYRIGHT file.
@ -14,3 +16,90 @@ AVAILABLE_LANGUAGE_CODES.each do |c|
I18n.fallbacks[c.to_sym] = [c.to_sym, DEFAULT_LANGUAGE.to_sym, :en] I18n.fallbacks[c.to_sym] = [c.to_sym, DEFAULT_LANGUAGE.to_sym, :en]
end end
end end
# Languages that require to specify biological gender (sex)
# in order to inflect properly when using nouns with second
# person in past tense.
module I18n
module Backend
module Genderize
# Languages that need and support inflection.
SupportedLanguages = [ :ar, :lt, :pl, :ru, :sr, :uk ]
# Genders table helps to initialize grammatical gender
# by looking at sociological gender entered by user.
Genders = {
:feminine => %w( f fem female feminine k kobieta pani woman
laska girl dziewczyna dziewucha chick lady mrs mrs.
miss missus missis mistress ms panna panienka ۃ
dziewczynka żona zena sayyidah Пані Госпожа Г-жа ),
:masculine => %w( m mal male masculine man dude guy gentleman
mr mister pan chłopak boy chłopiec koleś gość
lasek gostek monsieur hr herr Пан mr. سيد سادة
mężczyzna mąż chłopaczek facet sayyid Господин Г-н maleman ),
}
Genders.default = :neuter
end
end
end
# Grammatical gender aware translate.
module I18n
module Backend
module Genderize
def translate(locale, key, options = {})
subkey = options.delete(:gender)
if not (subkey.nil? || key.is_a?(Enumerable))
subkey = subkey.grammatical_gender if subkey.respond_to?(:grammatical_gender)
subkey = Genders.default unless Genders.has_key?(subkey.to_sym)
key = "#{key}.#{subkey}".to_sym
end
super(locale, key, options)
end
# Initialize fast mapping table using data from Genders.
def included(m)
return if instance_variable_defined?(:@genders_guesser)
@genders_guesser = {}
@known_genders = []
Genders.each_pair do |gname,gtable|
@known_genders.push gname
gtable.each do |word|
@genders_guesser[word.to_sym] = gname
end
end
@genders_guesser.default = Genders.default
@known_genders.push Genders.default
@known_genders.map! { |g| g.to_s }
nil
end
module_function :included
# Does language needs and supports inflection by gender?
def supports?(l=nil)
SupportedLanguages.include? l.nil? ? I18n.locale.to_sym : l.to_sym
end
module_function :supports?
# Deduce grammatical gender using given gender and mapping.
def guess(gender_description="")
@genders_guesser[gender_description.downcase.to_sym]
end
module_function :guess
# Array of strings with known grammatical genders.
def known_genders
@known_genders
end
module_function :known_genders
end
end
end
I18n::Backend::Simple.send(:include, I18n::Backend::Genderize)

View file

@ -21,7 +21,10 @@ en:
email: "Email" email: "Email"
password: "Password" password: "Password"
password_confirmation: "Password confirmation" password_confirmation: "Password confirmation"
are_you_sure: "Are you sure?" are_you_sure:
masculine: "Are you sure?"
feminine: "Are you sure?"
neuter: "Are you sure?"
fill_me_out: "Fill me out" fill_me_out: "Fill me out"
back: "Back" back: "Back"
the_world: "the world" the_world: "the world"
@ -103,7 +106,10 @@ en:
your_diaspora_username_is: "Your Diaspora username is: %{diaspora_handle}" your_diaspora_username_is: "Your Diaspora username is: %{diaspora_handle}"
create_request: "Find by Diaspora handle" create_request: "Find by Diaspora handle"
diaspora_handle: "diaspora@handle.org" diaspora_handle: "diaspora@handle.org"
know_email: "Know their email address? You should invite them" know_email:
masculine: "Know their email address? You should invite them"
feminine: "Know their email address? You should invite them"
neuter: "Know their email address? You should invite them"
invitations: invitations:
invite_someone: "Invite someone" invite_someone: "Invite someone"
invitations_left: "(%{count} left)" invitations_left: "(%{count} left)"
@ -159,7 +165,10 @@ en:
helper: helper:
remove: "remove" remove: "remove"
aspect_not_empty: "Aspect not empty" aspect_not_empty: "Aspect not empty"
are_you_sure: "Are you sure you want to delete this aspect?" are_you_sure:
masculine: "Are you sure you want to delete this aspect?"
feminine: "Are you sure you want to delete this aspect?"
neuter: "Are you sure you want to delete this aspect?"
remove_from_aspect: remove_from_aspect:
success: "Successfully removed person from aspect" success: "Successfully removed person from aspect"
failure: "Failed to remove person from aspect" failure: "Failed to remove person from aspect"
@ -183,6 +192,10 @@ en:
download_photos: "download my photos" download_photos: "download my photos"
your_handle: "Your diaspora handle" your_handle: "Your diaspora handle"
your_email: "Your email" your_email: "Your email"
address_me_as: "Address me as"
masculine: "a man"
feminine: "a woman"
neuter: "a neuter"
destroy: "Account successfully closed." destroy: "Account successfully closed."
getting_started: getting_started:
welcome: "Welcome to Diaspora!" welcome: "Welcome to Diaspora!"
@ -241,9 +254,18 @@ en:
back_to_list: "Back to List" back_to_list: "Back to List"
post_it: "post it!" post_it: "post it!"
create: create:
runtime_error: "Photo upload failed. Are you sure that your seatbelt is fastened?" runtime_error:
integrity_error: "Photo upload failed. Are you sure that was an image?" masculine: "Photo upload failed. Are you sure that your seatbelt is fastened?"
type_error: "Photo upload failed. Are you sure an image was added?" feminine: "Photo upload failed. Are you sure that your seatbelt is fastened?"
neuter: "Photo upload failed. Are you sure that your seatbelt is fastened?"
integrity_error:
masculine: "Photo upload failed. Are you sure that was an image?"
feminine: "Photo upload failed. Are you sure that was an image?"
neuter: "Photo upload failed. Are you sure that was an image?"
type_error:
masculine: "Photo upload failed. Are you sure an image was added?"
feminine: "Photo upload failed. Are you sure an image was added?"
neuter: "Photo upload failed. Are you sure an image was added?"
update: update:
notice: "Photo successfully updated." notice: "Photo successfully updated."
error: "Failed to edit photo." error: "Failed to edit photo."
@ -272,11 +294,20 @@ en:
sent: "Invitations have been sent to: " sent: "Invitations have been sent to: "
rejected: "The following email addresses had problems: " rejected: "The following email addresses had problems: "
no_more: "You have no more invitations." no_more: "You have no more invitations."
already_sent: "You already invited this person." already_sent:
already_contacts: "You are already connected with this person" masculine: "You already invited this person."
feminine: "You already invited this person."
neuter: "You already invited this person."
already_contacts:
masculine: "You are already connected with this person."
feminine: "You are already connected with this person."
neuter: "You are already connected with this person."
new: new:
invite_someone_to_join: "Invite someone to join Diaspora!" invite_someone_to_join: "Invite someone to join Diaspora!"
if_they_accept_info: "if they accept, they will be added to the aspect you invited them." if_they_accept_info:
masculine: "if they accept, they will be added to the aspect you invited them."
feminine: "if they accept, they will be added to the aspect you invited them."
neuter: "if they accept, they will be added to the aspect you invited them."
comma_seperated_plz: "You can enter multiple email addresses separated by commas." comma_seperated_plz: "You can enter multiple email addresses separated by commas."
to: "To" to: "To"
message: "Message:" message: "Message:"
@ -307,10 +338,16 @@ en:
incoming_request: "You have an incoming request from this person." incoming_request: "You have an incoming request from this person."
return_to_aspects: "Return to your aspects page" return_to_aspects: "Return to your aspects page"
to_accept_or_ignore: "to accept or ignore it." to_accept_or_ignore: "to accept or ignore it."
request_people: "If you'd like, you can request to place him/her in one of your aspects." request_people: "If you'd like, you can request to place him in one of your aspects."
already_requested: "You have already sent a request to %{name}." already_requested:
masculine: "You have already sent a request to %{name}."
feminine: "You have already sent a request to %{name}."
neuter: "You have already sent a request to %{name}."
does_not_exist: "Person does not exist!" does_not_exist: "Person does not exist!"
not_connected: "You are not connected with this person" not_connected:
masculine: "You are not connected with this person"
feminine: "You are not connected with this person"
neuter: "You are not connected with this person"
edit: edit:
info_available_to: "This info will be available to whomever you connect with on Diaspora." info_available_to: "This info will be available to whomever you connect with on Diaspora."
your_profile: "Your profile" your_profile: "Your profile"
@ -350,7 +387,10 @@ en:
ignore: "Ignored contact request." ignore: "Ignored contact request."
create: create:
sending: "Sending" sending: "Sending"
sent: "You've asked to share with %{name}. They should see it next time they log in to Diaspora." sent:
masculine: "You've asked to share with %{name}. They should see it next time they log in to Diaspora."
feminine: "You've asked to share with %{name}. They should see it next time they log in to Diaspora."
neuter: "You've asked to share with %{name}. They should see it next time they log in to Diaspora."
new_request_to_person: new_request_to_person:
sent: "sent!" sent: "sent!"
services: services:

View file

@ -11,7 +11,8 @@ describe UsersController do
let!(:old_password) { user.encrypted_password } let!(:old_password) { user.encrypted_password }
let!(:old_language) { user.language } let!(:old_language) { user.language }
let!(:old_gender) { user.grammatical_gender }
before do before do
sign_in :user, user sign_in :user, user
end end
@ -59,5 +60,28 @@ describe UsersController do
user.language.should_not == old_language user.language.should_not == old_language
end end
end end
describe 'grammatical_gender' do
it 'should allow user to change his grammatical gender for some languages' do
user.language = 'pl'
user.grammatical_gender = 'masculine'
user.save
old_gender = user.grammatical_gender
put("update", :id => user.id, "user" => {"language" => "ru", "grammatical_gender" => "neuter"})
user.reload
user.grammatical_gender.should_not == old_gender
old_gender = user.grammatical_gender
put("update", :id => user.id, "user" => {"language" => "ru", "grammatical_gender" => ""})
user.reload
user.grammatical_gender.should == old_gender
put("update", :id => user.id, "user" => {"language" => "ru", "grammatical_gender" => "feminine"})
user.reload
old_gender = user.grammatical_gender
put("update", :id => user.id, "user" => {"language" => "en"})
user.reload
user.grammatical_gender.should == old_gender
end
end
end end
end end

View file

@ -167,6 +167,22 @@ describe User do
end end
end end
describe "of grammatical gender" do
after do
I18n.locale = :en
end
it "requires availability" do
user = Factory.build(:user, :grammatical_gender => 'some invalid string')
user.should_not be_valid
end
it "should save with empty grammatical gender if blank" do
I18n.locale = :pl
user = Factory(:user, :grammatical_gender => nil)
user.grammatical_gender.should == nil
end
end
end end
describe ".build" do describe ".build" do