From ecd3f31242bfecf770ad76d9cb1613fc29900188 Mon Sep 17 00:00:00 2001 From: Antonio Terceiro Date: Mon, 5 Apr 2010 16:14:28 -0300 Subject: [PATCH] Replacing Ruby-GetText with fast_gettext --- app/controllers/application.rb | 17 ++++++----------- app/helpers/account_helper.rb | 1 - app/helpers/application_helper.rb | 13 +++++-------- app/helpers/categories_helper.rb | 1 - app/helpers/content_viewer_helper.rb | 1 - app/helpers/countries_helper.rb | 3 --- app/helpers/dates_helper.rb | 4 ++-- app/helpers/language_helper.rb | 7 +------ app/helpers/profile_editor_helper.rb | 1 - app/models/task.rb | 1 - app/views/layouts/application-ng.rhtml | 2 +- config/environment.rb | 11 ----------- config/initializers/dependencies.rb | 10 ++++++++++ config/initializers/fast_gettext.rb | 1 + features/step_definitions/internationalization_steps.rb | 16 ++++++---------- lib/noosfero.rb | 15 +++++++++------ lib/noosfero/i18n.rb | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/tasks/populate.rake | 2 -- lib/unifreire_terminology.rb | 1 - lib/zen3_terminology.rb | 1 - test/unit/communities_block_test.rb | 2 -- test/unit/enterprises_block_test.rb | 2 -- test/unit/friends_block_test.rb | 2 -- test/unit/language_helper_test.rb | 9 ++------- 24 files changed, 226 insertions(+), 80 deletions(-) create mode 100644 config/initializers/dependencies.rb create mode 100644 config/initializers/fast_gettext.rb create mode 100644 lib/noosfero/i18n.rb diff --git a/app/controllers/application.rb b/app/controllers/application.rb index f057400..7f147a8 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -70,20 +70,15 @@ class ApplicationController < ActionController::Base end end - include GetText - before_init_gettext :maybe_save_locale, :default_locale - def maybe_save_locale + before_filter :set_locale + def set_locale + FastGettext.available_locales = Noosfero.available_locales + FastGettext.default_locale = Noosfero.default_locale + FastGettext.set_locale(params[:lang] || session[:lang] || Noosfero.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en') if params[:lang] - cookies[:lang] = params[:lang] + session[:lang] = params[:lang] end end - def default_locale - if Noosfero.default_locale && cookies[:lang].blank? - cookies[:lang] = params[:lang] = Noosfero.default_locale - end - end - protected :maybe_save_locale, :default_locale - init_gettext 'noosfero' include NeedsProfile diff --git a/app/helpers/account_helper.rb b/app/helpers/account_helper.rb index 0c1b349..7ec71e9 100644 --- a/app/helpers/account_helper.rb +++ b/app/helpers/account_helper.rb @@ -1,6 +1,5 @@ module AccountHelper - include GetText def button_to_step(type, step, current_step, html_options = {}) if current_step == step diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 05da3b0..7b4321d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -26,6 +26,10 @@ module ApplicationHelper include AccountHelper + def locale + FastGettext.locale + end + def load_web2_conf if File.exists?( RAILS_ROOT + '/config/web2.0.yml') YAML.load_file( RAILS_ROOT + '/config/web2.0.yml' ) @@ -664,7 +668,6 @@ module ApplicationHelper # Should be on the forms_helper file but when its there the translation of labels doesn't work class NoosferoFormBuilder < ActionView::Helpers::FormBuilder - include GetText extend ActionView::Helpers::TagHelper def self.output_field(text, field_html, field_id = nil) @@ -687,13 +690,7 @@ module ApplicationHelper (field_helpers - %w(hidden_field)).each do |selector| src = <<-END_SRC def #{selector}(field, *args, &proc) - column = object.class.columns_hash[field.to_s] - text = - ( column ? - column.human_name : - field.to_s.humanize - ) - + text = object.class.human_attribute_name(field.to_s) NoosferoFormBuilder::output_field(text, super) end END_SRC diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb index d2a2972..1605b91 100644 --- a/app/helpers/categories_helper.rb +++ b/app/helpers/categories_helper.rb @@ -1,6 +1,5 @@ module CategoriesHelper - include GetText COLORS = [ [ N_('Do not display at the menu'), nil ], diff --git a/app/helpers/content_viewer_helper.rb b/app/helpers/content_viewer_helper.rb index fa4a46e..f9dd3d9 100644 --- a/app/helpers/content_viewer_helper.rb +++ b/app/helpers/content_viewer_helper.rb @@ -1,6 +1,5 @@ module ContentViewerHelper - include GetText include BlogHelper def number_of_comments(article) diff --git a/app/helpers/countries_helper.rb b/app/helpers/countries_helper.rb index 56466a2..944c519 100644 --- a/app/helpers/countries_helper.rb +++ b/app/helpers/countries_helper.rb @@ -2,9 +2,6 @@ class CountriesHelper include Singleton - include GetText - bindtextdomain 'iso_3166' - # a dump of iso_3166.xml from Debian source package iso-codes COUNTRIES = [ ["Afghanistan", "AF"], diff --git a/app/helpers/dates_helper.rb b/app/helpers/dates_helper.rb index fb47d98..4ecd670 100644 --- a/app/helpers/dates_helper.rb +++ b/app/helpers/dates_helper.rb @@ -1,6 +1,6 @@ -module DatesHelper +require 'noosfero/i18n' - include GetText +module DatesHelper # FIXME Date#strftime should translate this for us !!!! MONTHS = [ diff --git a/app/helpers/language_helper.rb b/app/helpers/language_helper.rb index 5b185d7..e7640de 100644 --- a/app/helpers/language_helper.rb +++ b/app/helpers/language_helper.rb @@ -1,11 +1,6 @@ module LanguageHelper def language - if Noosfero.available_locales.include?(locale.to_s) || - Noosfero.available_locales.include?(locale.language) - locale.language - else - Noosfero.default_locale || 'en' - end + locale end def tinymce_language diff --git a/app/helpers/profile_editor_helper.rb b/app/helpers/profile_editor_helper.rb index f2f4d5a..a004d88 100644 --- a/app/helpers/profile_editor_helper.rb +++ b/app/helpers/profile_editor_helper.rb @@ -1,6 +1,5 @@ module ProfileEditorHelper - include GetText AREAS_OF_STUDY = [ N_('Agrometeorology'), diff --git a/app/models/task.rb b/app/models/task.rb index d7b8f04..acccea3 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -12,7 +12,6 @@ class Task < ActiveRecord::Base module Status - include GetText # the status of tasks just created ACTIVE = 1 diff --git a/app/views/layouts/application-ng.rhtml b/app/views/layouts/application-ng.rhtml index 17e9923..d97d602 100644 --- a/app/views/layouts/application-ng.rhtml +++ b/app/views/layouts/application-ng.rhtml @@ -37,7 +37,7 @@ } - Ir para o conteúdo + <%= _("Go to the content") %>
diff --git a/config/environment.rb b/config/environment.rb index ad53b41..0706a74 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -10,17 +10,6 @@ RAILS_GEM_VERSION = '2.1.0' unless defined? RAILS_GEM_VERSION # Bootstrap the Rails environment, frameworks, and default configuration require File.join(File.dirname(__FILE__), 'boot') -# locally-developed modules -require 'locale' -require 'gettext/rails' -require 'acts_as_filesystem' -require 'acts_as_having_settings' -require 'acts_as_searchable' -require 'acts_as_having_boxes' -require 'acts_as_having_image' -require 'will_paginate' -require 'route_if' - # extra directories for controllers organization extra_controller_dirs = %w[ app/controllers/my_profile diff --git a/config/initializers/dependencies.rb b/config/initializers/dependencies.rb new file mode 100644 index 0000000..44cc43b --- /dev/null +++ b/config/initializers/dependencies.rb @@ -0,0 +1,10 @@ +# locally-developed modules +require 'acts_as_filesystem' +require 'acts_as_having_settings' +require 'acts_as_searchable' +require 'acts_as_having_boxes' +require 'acts_as_having_image' +require 'route_if' + +# third-party libraries +require 'will_paginate' diff --git a/config/initializers/fast_gettext.rb b/config/initializers/fast_gettext.rb new file mode 100644 index 0000000..43ef457 --- /dev/null +++ b/config/initializers/fast_gettext.rb @@ -0,0 +1 @@ +require 'noosfero/i18n' diff --git a/features/step_definitions/internationalization_steps.rb b/features/step_definitions/internationalization_steps.rb index 6e2e299..92cde6f 100644 --- a/features/step_definitions/internationalization_steps.rb +++ b/features/step_definitions/internationalization_steps.rb @@ -1,4 +1,4 @@ -def language_to_header(name) +def language_to_code(name) { 'Brazilian Portuguese' => 'pt-br', 'European Portuguese' => 'pt-pt', @@ -17,29 +17,25 @@ def native_name(name) }[name] || name end -def language_to_code(name) - language_to_header(name) -end - Given /^Noosfero is configured to use (.+) as default$/ do |lang| Noosfero.default_locale = language_to_code(lang) end -After('@default_locale_config') do +After do + # reset everything back to normal Noosfero.default_locale = nil + FastGettext.locale = 'en' end Given /^a user accessed in (.*) before$/ do |lang| session = Webrat::Session.new(Webrat.adapter_class.new(self)) session.extend(Webrat::Matchers) session.visit('/') - session.should have_selector('html[lang=en]') + session.should have_selector("html[lang=#{language_to_code(lang)}]") end Given /^my browser prefers (.*)$/ do |lang| - @n ||= 0 - header 'Accept-Language', language_to_header(lang) - + header 'Accept-Language', language_to_code(lang) end Then /^the site should be in (.*)$/ do |lang| diff --git a/lib/noosfero.rb b/lib/noosfero.rb index 69ddc65..709cbc8 100644 --- a/lib/noosfero.rb +++ b/lib/noosfero.rb @@ -12,12 +12,15 @@ module Noosfero attr_accessor :locales attr_accessor :default_locale def available_locales - @available_locales ||= locales.keys - end - def each_locale - locales.keys.sort.each do |key| - yield(key, locales[key]) - end + @available_locales ||= + begin + locales_list = locales.keys + # move English to the beginning + if locales_list.include?('en') + locales_list = ['en'] + (locales_list - ['en']).sort + end + locales_list + end end end diff --git a/lib/noosfero/i18n.rb b/lib/noosfero/i18n.rb new file mode 100644 index 0000000..24f8206 --- /dev/null +++ b/lib/noosfero/i18n.rb @@ -0,0 +1,183 @@ +require 'fast_gettext' + +class Object + include FastGettext::Translation + alias :gettext :_ + alias :ngettext :n_ +end + +class ActiveRecord::Errors + default_error_messages.update( + :inclusion => N_("%{fn} is not included in the list"), + :exclusion => N_("%{fn} is reserved"), + :invalid => N_("%{fn} is invalid"), + :confirmation => N_("%{fn} doesn't match confirmation"), + :accepted => N_("%{fn} must be accepted"), + :empty => N_("%{fn} can't be empty"), + :blank => N_("%{fn} can't be blank"), + :too_long => N_("%{fn} is too long (maximum is %d characters)"), + :too_short => N_("%{fn} is too short (minimum is %d characters)"), + :wrong_length => N_("%{fn} is the wrong length (should be %d characters)"), + :taken => N_("%{fn} has already been taken"), + :not_a_number => N_("%{fn} is not a number") + ) + + def localize_error_messages + errors = {} + each do |attr,msg| + next if msg.nil? + errors[attr] ||= [] + errors[attr] << _(msg).sub('%{fn}', @base.class.human_attribute_name(attr)) + end + errors + end + def on_with_gettext(attribute) + errors = localize_error_messages[attribute.to_s] + return nil if errors.nil? + errors.size == 1 ? errors.first : errors + end + alias_method_chain :on, :gettext + + def full_messages_with_gettext + full_messages = [] + errors = localize_error_messages + errors.each_key do |attr| + errors[attr].each do |msg| + next if msg.nil? + full_messages << msg + end + end + full_messages + end + alias_method_chain :full_messages, :gettext +end + + +module ActionView::Helpers::ActiveRecordHelper + module L10n + @error_message_title = Nn_("%{num} error prohibited this %{record} from being saved", "%{num} errors prohibited this %{record} from being saved").flatten + @error_message_explanation = Nn_("There was a problem with the following field:", "There were problems with the following fields:").flatten + module_function + def error_messages_for(instance, objects, object_names, count, options) + record = _(options[:object_name] || object_names[0].to_s) + + html = {} + [:id, :class].each do |key| + if options.include?(key) + value = options[key] + html[key] = value unless value.blank? + else + html[key] = 'errorExplanation' + end + end + + if options[:message_title] + header_message = instance.error_message(options[:message_title], count) % {:num => count, :record => record} + else + header_message = ((count == 1) ? _(@error_message_title[0]) : _(@error_message_title[1])) % {:num => count, :record => record} + end + if options[:message_explanation] + message_explanation = instance.error_message(options[:message_explanation], count) % {:num => count} + else + message_explanation = (count == 1 ? _(@error_message_explanation[0]) : _(@error_message_explanation[1])) % {:num => count} + end + + error_messages = objects.map {|object| object.errors.full_messages.map {|msg| instance.content_tag(:li, msg) } } + + instance.content_tag( + :div, + instance.content_tag(options[:header_tag] || :h2, header_message) << + instance.content_tag(:p, message_explanation) << + instance.content_tag(:ul, error_messages), + html + ) + end + end + + alias error_messages_for_without_localize error_messages_for #:nodoc: + + # error_messages_for overrides original method with localization. + # And also it extends to be able to replace the title/explanation of the header of the error dialog. (Since 1.90) + # If you want to override these messages in the whole application, + # use ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_(title|explanation) instead. + # * :message_title - the title of message. Use Nn_() to path the strings for singular/plural. + # e.g. Nn_("%{num} error prohibited this %{record} from being saved", + # "%{num} errors prohibited this %{record} from being saved") + # * :message_explanation - the explanation of message + # e.g. Nn_("There was a problem with the following field:", + # "There were %{num} problems with the following fields:") + def error_messages_for(*params) + options = params.last.is_a?(Hash) ? params.pop.symbolize_keys : {} + objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact + object_names = params.dup + count = objects.inject(0) {|sum, object| sum + object.errors.count } + if count.zero? + '' + else + L10n.error_messages_for(self, objects, object_names, count, options) + end + end + +end + +module ActionController::Caching::Fragments + def fragment_cache_key_with_fast_gettext(name) + ret = fragment_cache_key_without_fast_gettext(name) + if ret.is_a? String + ret.gsub(/:/, ".") << "_#{FastGettext.locale}" + else + ret + end + end + alias_method_chain :fragment_cache_key, :fast_gettext + + def expire_fragment_with_fast_gettext(name, options = nil) + return unless perform_caching + + key = fragment_cache_key_without_fast_gettext(name) + if key.is_a?(Regexp) + self.class.benchmark "Expired fragments matching: #{key.source}" do + fragment_cache_store.delete_matched(key, options) + end + else + key = key.gsub(/:/, ".") + self.class.benchmark "Expired fragment: #{key}, lang = #{FastGettext.available_locales.inspect}" do + if FastGettext.available_locales + FastGettext.available_locales.each do |lang| + fragment_cache_store.delete("#{key}_#{lang}", options) + end + end + end + end + end + alias_method_chain :expire_fragment, :fast_gettext +end + +FileUtils.mkdir_p(Rails.root + '/locale') +Dir.glob(Rails.root + '/locale/*').each do |dir| + lang = File.basename(dir) + FileUtils.mkdir_p("#{Rails.root}/locale/#{lang}/LC_MESSAGES") + ['iso_3166', 'rails'].each do |domain| + target = "#{Rails.root}/locale/#{lang}/LC_MESSAGES/#{domain}.mo" + if !File.exists?(target) + orig = "/usr/share/locale/#{lang}/LC_MESSAGES/#{domain}.mo" + if File.exists?(orig) + File.symlink(orig, target) + else + alternatives = Dir.glob("/usr/share/locale/#{lang}_*/LC_MESSAGES/#{domain}.mo") + unless alternatives.empty? + File.symlink(alternatives.first, target) + end + end + end + end +end + +repos = [ + FastGettext::TranslationRepository.build('noosfero', :type => 'mo', :path => Rails.root + '/locale'), + FastGettext::TranslationRepository.build('iso_3166', :type => 'mo', :path => Rails.root + '/locale'), + FastGettext::TranslationRepository.build('rails', :type => 'mo', :path => Rails.root + '/locale'), +] + +FastGettext.add_text_domain 'noosferofull', :type => :chain, :chain => repos +FastGettext.default_text_domain = 'noosferofull' diff --git a/lib/tasks/populate.rake b/lib/tasks/populate.rake index 07330da..381babf 100644 --- a/lib/tasks/populate.rake +++ b/lib/tasks/populate.rake @@ -1,7 +1,5 @@ require File.dirname(__FILE__) + '/../../config/environment' require 'noosfero' -require 'gettext/rails' -include GetText DEFAULT_ENVIRONMENT_TEXT = <Environment homepage diff --git a/lib/unifreire_terminology.rb b/lib/unifreire_terminology.rb index 42b3b49..3c9d596 100644 --- a/lib/unifreire_terminology.rb +++ b/lib/unifreire_terminology.rb @@ -1,7 +1,6 @@ require 'noosfero/terminology' class UnifreireTerminology < Noosfero::Terminology::Custom - include GetText def initialize # NOTE: the hash values must be marked for translation!! diff --git a/lib/zen3_terminology.rb b/lib/zen3_terminology.rb index 2fb8377..09f4f4f 100644 --- a/lib/zen3_terminology.rb +++ b/lib/zen3_terminology.rb @@ -1,7 +1,6 @@ require 'noosfero/terminology' class Zen3Terminology < Noosfero::Terminology::Custom - include GetText def initialize # NOTE: the hash values must be marked for translation!! diff --git a/test/unit/communities_block_test.rb b/test/unit/communities_block_test.rb index ae1cf72..07cceba 100644 --- a/test/unit/communities_block_test.rb +++ b/test/unit/communities_block_test.rb @@ -2,8 +2,6 @@ require File.dirname(__FILE__) + '/../test_helper' class CommunitiesBlockTest < Test::Unit::TestCase - include GetText - should 'inherit from ProfileListBlock' do assert_kind_of ProfileListBlock, CommunitiesBlock.new end diff --git a/test/unit/enterprises_block_test.rb b/test/unit/enterprises_block_test.rb index 3b3be1a..ec8f204 100644 --- a/test/unit/enterprises_block_test.rb +++ b/test/unit/enterprises_block_test.rb @@ -2,8 +2,6 @@ require File.dirname(__FILE__) + '/../test_helper' class EnterprisesBlockTest < Test::Unit::TestCase - include GetText - should 'inherit from ProfileListBlock' do assert_kind_of ProfileListBlock, EnterprisesBlock.new end diff --git a/test/unit/friends_block_test.rb b/test/unit/friends_block_test.rb index 82c9f60..9004ff1 100644 --- a/test/unit/friends_block_test.rb +++ b/test/unit/friends_block_test.rb @@ -2,8 +2,6 @@ require File.dirname(__FILE__) + '/../test_helper' class FriendsBlockTest < ActiveSupport::TestCase - include GetText - should 'describe itself' do assert_not_equal ProfileListBlock.description, FriendsBlock.description end diff --git a/test/unit/language_helper_test.rb b/test/unit/language_helper_test.rb index 5cc3ff0..11a7c8e 100644 --- a/test/unit/language_helper_test.rb +++ b/test/unit/language_helper_test.rb @@ -4,14 +4,9 @@ class LanguageHelperTest < Test::Unit::TestCase include LanguageHelper - should 'return current language' do - locale = mock - locale.stubs(:to_s).returns('pt_BR') - locale.stubs(:language).returns('pt') - stubs(:locale).returns(locale) - - assert_equal 'pt', self.language + expects(:locale).returns('pt') + assert_equal 'pt', language end should 'remove country code for TinyMCE' do -- libgit2 0.21.2