Added inflection of nouns by the grammatical gender for some languages.
- New module I18n::Backend::Genderize keeps configuration and adds :gender option to translate(). - Module methods in Genderize allow fast checking if language needs gender and guessing gender. - jQuery in views/users/edit.html.haml shows and hides grammatical gender select list when needed. - Span and select list in views/users/edit.html.haml allows to choose grammatical gender. - Key :grammatical_gender in User model keeps grammatical gender information. - Added some methods to language_helper.rb. - UsersController is aware of grammatical gender and is able to guess it when "getting started".
This commit is contained in:
parent
b2f4e064fc
commit
279b08ae4a
5 changed files with 156 additions and 10 deletions
|
|
@ -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,10 +38,18 @@ 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])
|
||||||
|
if params[:user][:grammatical_gender]
|
||||||
|
if @user.update_attributes(:grammatical_gender => params[:user][:grammatical_gender])
|
||||||
flash[:notice] = I18n.t 'users.update.language_changed'
|
flash[:notice] = I18n.t 'users.update.language_changed'
|
||||||
else
|
else
|
||||||
flash[:error] = I18n.t 'users.update.language_not_changed'
|
flash[:error] = I18n.t 'users.update.language_not_changed'
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
flash[:notice] = I18n.t 'users.update.language_changed'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
flash[:error] = I18n.t 'users.update.language_not_changed'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to edit_user_path(@user)
|
redirect_to edit_user_path(@user)
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,30 @@ module LanguageHelper
|
||||||
end
|
end
|
||||||
options.sort_by { |o| o[0] }
|
options.sort_by { |o| o[0] }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def options_for_gender_select(user)
|
||||||
|
grammatical_gender = 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(user)
|
||||||
|
not I18n::Backend::Genderize.supports?(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(user)
|
||||||
|
enabled = I18n::Backend::Genderize.supports? user.language
|
||||||
|
{:style => 'display: ' + (enabled ? 'inline' : 'none') + ';' +
|
||||||
|
' margin-left: 1em; margin-right: 0.5em;'
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -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?
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,10 @@
|
||||||
-# the COPYRIGHT file.
|
-# the COPYRIGHT file.
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
|
var genderized_languages = #{grammatical_gender_languages}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
$("#settings_nav li > a").live("click", function() {
|
$("#settings_nav li > a").live("click", function() {
|
||||||
var target = "#"+$(this).attr('class');
|
var target = "#"+$(this).attr('class');
|
||||||
if( !$(target).is(":visible") ) {
|
if( !$(target).is(":visible") ) {
|
||||||
|
|
@ -12,6 +16,18 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#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
|
||||||
%h2
|
%h2
|
||||||
= t('settings')
|
= t('settings')
|
||||||
|
|
@ -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(current_user)}
|
||||||
|
= " " + t('.address_me_as')
|
||||||
|
= select_tag 'user[grammatical_gender]', options_for_gender_select(current_user), :disabled => gender_select_disabled(current_user)
|
||||||
= f.submit t('.change_language')
|
= f.submit t('.change_language')
|
||||||
|
|
||||||
%br
|
%br
|
||||||
|
|
|
||||||
|
|
@ -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 = {})
|
||||||
|
g = options.delete(:gender)
|
||||||
|
if not (g.nil? || key.is_a?(Enumerable))
|
||||||
|
g = g.to_sym
|
||||||
|
subkey = Genders[g.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)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue