diff options
Diffstat (limited to 'vendor/plugins/gettext_i18n_rails')
24 files changed, 1192 insertions, 0 deletions
diff --git a/vendor/plugins/gettext_i18n_rails/Rakefile b/vendor/plugins/gettext_i18n_rails/Rakefile new file mode 100644 index 000000000..ac396d4d4 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/Rakefile @@ -0,0 +1,25 @@ +require "rspec/core/rake_task" +RSpec::Core::RakeTask.new(:spec) do |t| + t.rspec_opts = '--backtrace --color' +end + +task :default do + puts `rake spec VERSION=2.3.10 RSPEC_COLOR=1` + puts `rake spec VERSION=3.0.3 RSPEC_COLOR=1` +end + +begin + require 'jeweler' + Jeweler::Tasks.new do |gem| + gem.name = 'gettext_i18n_rails' + gem.summary = "Simple FastGettext Rails integration." + gem.email = "grosser.michael@gmail.com" + gem.homepage = "http://github.com/grosser/#{gem.name}" + gem.authors = ["Michael Grosser"] + gem.add_dependency 'fast_gettext' + end + + Jeweler::GemcutterTasks.new +rescue LoadError + puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler" +end diff --git a/vendor/plugins/gettext_i18n_rails/Readme.md b/vendor/plugins/gettext_i18n_rails/Readme.md new file mode 100644 index 000000000..d3e11845f --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/Readme.md @@ -0,0 +1,215 @@ +[FastGettext](http://github.com/grosser/fast_gettext) / Rails integration. + +Translate via FastGettext, use any other I18n backend as extension/fallback. + +Rails does: `I18n.t('syntax.with.lots.of.dots')` with nested yml files +We do: `_('Just translate my damn text!')` with simple, flat mo/po/yml files or directly from db +To use I18n calls add a `syntax.with.lots.of.dots` translation. + +[See it working in the example application.](https://github.com/grosser/gettext_i18n_rails_example) + +Setup +===== +### Installation + +#### Rails 3 + +##### As plugin: + + rails plugin install git://github.com/grosser/gettext_i18n_rails.git + + # Gemfile + gem 'fast_gettext', '>=0.4.8' + +##### As gem: + + # Gemfile + gem 'gettext_i18n_rails' + +##### Optional: +If you want to find translations or build .mo files + # Gemfile + gem 'gettext', '>=1.9.3', :require => false, :group => :development + +#### Rails 2 + +##### As plugin: + + script/plugin install git://github.com/grosser/gettext_i18n_rails.git + sudo gem install fast_gettext + + # config/environment.rb + config.gem "fast_gettext", :version => '>=0.4.8' + +##### As gem: + + gem install gettext_i18n_rails + + # config/environment.rb + config.gem 'gettext_i18n_rails' + + #Rakefile + begin + require "gettext_i18n_rails/tasks" + rescue LoadError + puts "gettext_i18n_rails is not installed, you probably should run 'rake gems:install' or 'bundle install'." + end + +##### Optional: +If you want to find translations or build .mo files + # config/environments/development.rb + config.gem "gettext", :version => '>=1.9.3', :lib => false + +### Locales & initialisation +Copy default locales with dates/sentence-connectors/AR-errors you want from e.g. +[rails i18n](http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale/) into 'config/locales' + +To initialize: + + # config/initializers/fast_gettext.rb + FastGettext.add_text_domain 'app', :path => 'locale', :type => :po + FastGettext.default_available_locales = ['en','de'] #all you want to allow + FastGettext.default_text_domain = 'app' + +And in your application: + + # app/controllers/application_controller.rb + class ApplicationController < ... + before_filter :set_gettext_locale + +Translating +=========== +Performance is almost the same for all backends since translations are cached after first use. + +### Option A: .po files + + FastGettext.add_text_domain 'app', :path => 'locale', :type => :po + + - use some _('translations') + - run `rake gettext:find`, to let GetText find all translations used + - (optional) run `rake gettext:store_model_attributes`, to parse the database for columns that can be translated + - if this is your first translation: `cp locale/app.pot locale/de/app.po` for every locale you want to use + - translate messages in 'locale/de/app.po' (leave msgstr blank and msgstr == msgid) + +New translations will be marked "fuzzy", search for this and remove it, so that they will be used. +Obsolete translations are marked with ~#, they usually can be removed since they are no longer needed + +#### Unfound translations with rake gettext:find +Dynamic translations like `_("x"+"u")` cannot be fond. You have 4 options: + + - add `N_('xu')` somewhere else in the code, so the parser sees it + - add `N_('xu')` in a totally separate file like `locale/unfound_translations.rb`, so the parser sees it + - use the [gettext_test_log rails plugin ](http://github.com/grosser/gettext_test_log) to find all translations that where used while testing + - add a Logger to a translation Chain, so every unfound translations is logged ([example]((http://github.com/grosser/fast_gettext))) + +### Option B: Traditional .po/.mo files + + FastGettext.add_text_domain 'app', :path => 'locale' + + - follow Option A + - run `rake gettext:pack` to write binary GetText .mo files + +### Option C: Database +Most scalable method, all translators can work simultaneously and online. + +Easiest to use with the [translation database Rails engine](http://github.com/grosser/translation_db_engine). +Translations can be edited under `/translation_keys` + + FastGettext::TranslationRepository::Db.require_models + FastGettext.add_text_domain 'app', :type => :db, :model => TranslationKey + +I18n +==== + I18n.locale <==> FastGettext.locale.to_sym + I18n.locale = :de <==> FastGettext.locale = 'de' + +Any call to I18n that matches a gettext key will be translated through FastGettext. + +Namespaces +========== +Car|Model means Model in namespace Car. +You do not have to translate this into english "Model", if you use the +namespace-aware translation + s_('Car|Model') == 'Model' #when no translation was found + +XSS / html_safe +=============== +If you trust your translators and all your usages of % on translations:<br/> + # config/environment.rb + GettextI18nRails.translations_are_html_safe = true + +String % vs html_safe is buggy (can be used for XSS on 1.8 and is always non-safe in 1.9)<br/> +My recommended fix is: `require 'gettext_i18n_rails/string_interpolate_fix'` + + - safe stays safe (escape added strings) + - unsafe stays unsafe (do not escape added strings) + +ActiveRecord - error messages +============================= +ActiveRecord error messages are translated through Rails::I18n, but +model names and model attributes are translated through FastGettext. +Therefore a validation error on a BigCar's wheels_size needs `_('big car')` and `_('BigCar|Wheels size')` +to display localized. + +The model/attribute translations can be found through `rake gettext:store_model_attributes`, +(which ignores some commonly untranslated columns like id,type,xxx_count,...). + +Error messages can be translated through FastGettext, if the ':message' is a translation-id or the matching Rails I18n key is translated. + +####Option A: +Define a translation for "I need my rating!" and use it as message. + validates_inclusion_of :rating, :in=>1..5, :message=>N_('I need my rating!') + +####Option B: + validates_inclusion_of :rating, :in=>1..5 +Make a translation for the I18n key: `activerecord.errors.models.rating.attributes.rating.inclusion` + +####Option C: +Add a translation to each config/locales/*.yml files + en: + activerecord: + errors: + models: + rating: + attributes: + rating: + inclusion: " -- please choose!" +The [rails I18n guide](http://guides.rubyonrails.org/i18n.html) can help with Option B and C. + +Plurals +======= +FastGettext supports pluralization + n_('Apple','Apples',3) == 'Apples' + +Abnormal plurals like e.g. Polish that has 4 different can also be addressed, see [FastGettext Readme](http://github.com/grosser/fast_gettext) + +Customizing list of translatable files +====================================== +When you run + + rake gettext:find + +by default the following files are going to be scanned for translations: {app,lib,config,locale}/**/*.{rb,erb,haml}. If +you want to specify a different list, you can redefine files_to_translate in the gettext namespace in a file like +lib/tasks/gettext.rake: + + namespace :gettext do + def files_to_translate + Dir.glob("{app,lib,config,locale}/**/*.{rb,erb,haml,rhtml}") + end + end + +[Contributors](http://github.com/grosser/gettext_i18n_rails/contributors) +====== + - [ruby gettext extractor](http://github.com/retoo/ruby_gettext_extractor/tree/master) from [retoo](http://github.com/retoo) + - [Paul McMahon](http://github.com/pwim) + - [Duncan Mac-Vicar P](http://duncan.mac-vicar.com/blog) + - [Ramihajamalala Hery](http://my.rails-royce.org) + - [J. Pablo Fernández](http://pupeno.com) + - [Anh Hai Trinh](http://blog.onideas.ws) + - [ed0h](http://github.com/ed0h) + - [Nikos Dimitrakopoulos](http://blog.nikosd.com) + +[Michael Grosser](http://grosser.it)<br/> +grosser.michael@gmail.com<br/> +Hereby placed under public domain, do what you want, just do not hold me accountable... diff --git a/vendor/plugins/gettext_i18n_rails/VERSION b/vendor/plugins/gettext_i18n_rails/VERSION new file mode 100644 index 000000000..dd767842d --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/VERSION @@ -0,0 +1 @@ +0.2.17
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec b/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec new file mode 100644 index 000000000..002b3ba0b --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec @@ -0,0 +1,65 @@ +# Generated by jeweler +# DO NOT EDIT THIS FILE DIRECTLY +# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{gettext_i18n_rails} + s.version = "0.2.17" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Michael Grosser"] + s.date = %q{2011-02-17} + s.email = %q{grosser.michael@gmail.com} + s.files = [ + "Rakefile", + "Readme.md", + "VERSION", + "gettext_i18n_rails.gemspec", + "init.rb", + "lib/gettext_i18n_rails.rb", + "lib/gettext_i18n_rails/action_controller.rb", + "lib/gettext_i18n_rails/active_record.rb", + "lib/gettext_i18n_rails/backend.rb", + "lib/gettext_i18n_rails/haml_parser.rb", + "lib/gettext_i18n_rails/html_safe_translations.rb", + "lib/gettext_i18n_rails/i18n_hacks.rb", + "lib/gettext_i18n_rails/model_attributes_finder.rb", + "lib/gettext_i18n_rails/railtie.rb", + "lib/gettext_i18n_rails/ruby_gettext_extractor.rb", + "lib/gettext_i18n_rails/string_interpolate_fix.rb", + "lib/gettext_i18n_rails/tasks.rb", + "lib/tasks/gettext_rails_i18n.rake", + "spec/gettext_i18n_rails/action_controller_spec.rb", + "spec/gettext_i18n_rails/active_record_spec.rb", + "spec/gettext_i18n_rails/backend_spec.rb", + "spec/gettext_i18n_rails/string_interpolate_fix_spec.rb", + "spec/gettext_i18n_rails_spec.rb", + "spec/spec_helper.rb" + ] + s.homepage = %q{http://github.com/grosser/gettext_i18n_rails} + s.require_paths = ["lib"] + s.rubygems_version = %q{1.4.2} + s.summary = %q{Simple FastGettext Rails integration.} + s.test_files = [ + "spec/gettext_i18n_rails/action_controller_spec.rb", + "spec/gettext_i18n_rails/active_record_spec.rb", + "spec/gettext_i18n_rails/backend_spec.rb", + "spec/gettext_i18n_rails/string_interpolate_fix_spec.rb", + "spec/gettext_i18n_rails_spec.rb", + "spec/spec_helper.rb" + ] + + if s.respond_to? :specification_version then + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q<fast_gettext>, [">= 0"]) + else + s.add_dependency(%q<fast_gettext>, [">= 0"]) + end + else + s.add_dependency(%q<fast_gettext>, [">= 0"]) + end +end + diff --git a/vendor/plugins/gettext_i18n_rails/init.rb b/vendor/plugins/gettext_i18n_rails/init.rb new file mode 100644 index 000000000..d218eee63 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/init.rb @@ -0,0 +1,14 @@ +begin + require 'config/initializers/session_store' +rescue LoadError + # weird bug, when run with rake rails reports error that session + # store is not configured, this fixes it somewhat... +end + +if Rails::VERSION::MAJOR > 2 + require 'gettext_i18n_rails' +else + #requires fast_gettext to be present. + #We give rails a chance to install it using rake gems:install, by loading it later. + config.after_initialize { require 'gettext_i18n_rails' } +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb new file mode 100644 index 000000000..6bf342bf3 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb @@ -0,0 +1,27 @@ +module GettextI18nRails + VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip + + extend self +end + +require 'fast_gettext' +if Gem::Version.new(FastGettext::VERSION) < Gem::Version.new("0.4.8") + raise "Please upgrade fast_gettext" +end + +# include translations into all the places it needs to go... +Object.send(:include, FastGettext::Translation) + +# make translations html_safe if possible and wanted +if "".respond_to?(:html_safe?) + require 'gettext_i18n_rails/html_safe_translations' + Object.send(:include, GettextI18nRails::HtmlSafeTranslations) +end + +require 'gettext_i18n_rails/backend' +I18n.backend = GettextI18nRails::Backend.new + +require 'gettext_i18n_rails/i18n_hacks' +require 'gettext_i18n_rails/active_record' if defined?(ActiveRecord) +require 'gettext_i18n_rails/action_controller' if defined?(ActionController) # so that bundle console can work in a rails project +require 'gettext_i18n_rails/railtie' diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/action_controller.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/action_controller.rb new file mode 100644 index 000000000..f5871bcc6 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/action_controller.rb @@ -0,0 +1,6 @@ +class ActionController::Base + def set_gettext_locale + requested_locale = params[:locale] || session[:locale] || cookies[:locale] || request.env['HTTP_ACCEPT_LANGUAGE'] + session[:locale] = FastGettext.set_locale(requested_locale) + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb new file mode 100644 index 000000000..9b238ac91 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb @@ -0,0 +1,21 @@ +class ActiveRecord::Base + # CarDealer.sales_count -> s_('CarDealer|Sales count') -> 'Sales count' if no translation was found + def self.human_attribute_name(attribute, *args) + s_(gettext_translation_for_attribute_name(attribute)) + end + + # CarDealer -> _('car dealer') + def self.human_name(*args) + _(self.human_name_without_translation) + end + + def self.human_name_without_translation + self.to_s.underscore.gsub('_',' ') + end + + private + + def self.gettext_translation_for_attribute_name(attribute) + "#{self}|#{attribute.to_s.split('.').map! {|a| a.gsub('_',' ').capitalize }.join('|')}" + end +end diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb new file mode 100644 index 000000000..10cf0a8c2 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb @@ -0,0 +1,63 @@ +module GettextI18nRails + #translates i18n calls to gettext calls + class Backend + @@translate_defaults = true + cattr_accessor :translate_defaults + attr_accessor :backend + + def initialize(*args) + self.backend = I18n::Backend::Simple.new(*args) + end + + def available_locales + FastGettext.available_locales || [] + end + + def translate(locale, key, options) + if gettext_key = gettext_key(key, options) + translation = FastGettext._(gettext_key) + interpolate(translation, options) + else + backend.translate locale, key, options + end + end + + def method_missing(method, *args) + backend.send(method, *args) + end + + protected + + def gettext_key(key, options) + flat_key = flatten_key key, options + if FastGettext.key_exist?(flat_key) + flat_key + elsif self.class.translate_defaults + [*options[:default]].each do |default| + #try the scoped(more specific) key first e.g. 'activerecord.errors.my custom message' + flat_key = flatten_key default, options + return flat_key if FastGettext.key_exist?(flat_key) + + #try the short key thereafter e.g. 'my custom message' + return default if FastGettext.key_exist?(default) + end + return nil + end + end + + def interpolate(string, values) + reserved_keys = if defined?(I18n::RESERVED_KEYS) # rails 3+ + I18n::RESERVED_KEYS + else + I18n::Backend::Base::RESERVED_KEYS + end + + string % values.except(*reserved_keys) + end + + def flatten_key key, options + scope = [*(options[:scope] || [])] + scope.empty? ? key.to_s : "#{scope*'.'}.#{key}" + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/haml_parser.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/haml_parser.rb new file mode 100644 index 000000000..04209b23f --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/haml_parser.rb @@ -0,0 +1,43 @@ +require 'gettext/utils' +begin + require 'gettext/tools/rgettext' +rescue LoadError #version prior to 2.0 + require 'gettext/rgettext' +end + +module GettextI18nRails + module HamlParser + module_function + + def target?(file) + File.extname(file) == '.haml' + end + + def parse(file, msgids = []) + return msgids unless load_haml + require 'gettext_i18n_rails/ruby_gettext_extractor' + + text = IO.readlines(file).join + + haml = Haml::Engine.new(text) + code = haml.precompiled + return RubyGettextExtractor.parse_string(code, file, msgids) + end + + def load_haml + return true if @haml_loaded + begin + require "#{::Rails.root.to_s}/vendor/plugins/haml/lib/haml" + rescue LoadError + begin + require 'haml' # From gem + rescue LoadError + puts "A haml file was found, but haml library could not be found, so nothing will be parsed..." + return false + end + end + @haml_loaded = true + end + end +end +GetText::RGetText.add_parser(GettextI18nRails::HamlParser)
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/html_safe_translations.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/html_safe_translations.rb new file mode 100644 index 000000000..1fc5f93f9 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/html_safe_translations.rb @@ -0,0 +1,29 @@ +module GettextI18nRails + mattr_accessor :translations_are_html_safe + + module HtmlSafeTranslations + # also make available on class methods + def self.included(base) + base.extend self + end + + def _(*args) + html_safe_if_wanted super + end + + def n_(*args) + html_safe_if_wanted super + end + + def s_(*args) + html_safe_if_wanted super + end + + private + + def html_safe_if_wanted(text) + return text unless GettextI18nRails.translations_are_html_safe + text.to_s.html_safe + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/i18n_hacks.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/i18n_hacks.rb new file mode 100644 index 000000000..3a8ee6f65 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/i18n_hacks.rb @@ -0,0 +1,38 @@ +module I18n + module_function + + def locale=(new_locale) + FastGettext.locale = new_locale + end + + def locale + FastGettext.locale.to_sym + end + + # since Rails 2.3.8 a config object is used instead of just .locale + if defined? Config + class Config + def locale + FastGettext.locale.to_sym + end + + def locale=(new_locale) + FastGettext.locale=(new_locale) + end + end + end + + # backport I18n.with_locale if it does not exist + unless respond_to?(:with_locale) + # Executes block with given I18n.locale set. + def with_locale(tmp_locale = nil) + if tmp_locale + current_locale = self.locale + self.locale = tmp_locale + end + yield + ensure + self.locale = current_locale if tmp_locale + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb new file mode 100644 index 000000000..e65bb52d6 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb @@ -0,0 +1,52 @@ +module GettextI18nRails + #write all found models/columns to a file where GetTexts ruby parser can find them + def store_model_attributes(options) + file = options[:to] || 'locale/model_attributes.rb' + File.open(file,'w') do |f| + f.puts "#DO NOT MODIFY! AUTOMATICALLY GENERATED FILE!" + ModelAttributesFinder.new.find(options).each do |table_name,column_names| + #model name + begin + model = table_name.singularize.camelcase.constantize + rescue NameError + # Some tables are not models, for example: translation tables created by globalize2. + next + end + f.puts("_('#{model.human_name_without_translation}')") + + #all columns namespaced under the model + column_names.each do |attribute| + translation = model.gettext_translation_for_attribute_name(attribute) + f.puts("_('#{translation}')") + end + end + f.puts "#DO NOT MODIFY! AUTOMATICALLY GENERATED FILE!" + end + end + module_function :store_model_attributes + + class ModelAttributesFinder + # options: + # :ignore_tables => ['cars',/_settings$/,...] + # :ignore_columns => ['id',/_id$/,...] + # current connection ---> {'cars'=>['model_name','type'],...} + def find(options) + found = Hash.new([]) + + connection = ActiveRecord::Base.connection + connection.tables.each do |table_name| + next if ignored?(table_name,options[:ignore_tables]) + connection.columns(table_name).each do |column| + found[table_name] += [column.name] unless ignored?(column.name,options[:ignore_columns]) + end + end + + found + end + + def ignored?(name,patterns) + return false unless patterns + patterns.detect{|p|p.to_s==name.to_s or (p.is_a?(Regexp) and name=~p)} + end + end +end diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/railtie.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/railtie.rb new file mode 100644 index 000000000..174e1afb9 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/railtie.rb @@ -0,0 +1,10 @@ +# add rake tasks if we are inside Rails +if defined?(Rails::Railtie) + module GettextI18nRails + class Railtie < ::Rails::Railtie + rake_tasks do + require 'gettext_i18n_rails/tasks' + end + end + end +end diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/ruby_gettext_extractor.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/ruby_gettext_extractor.rb new file mode 100644 index 000000000..74031ca5a --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/ruby_gettext_extractor.rb @@ -0,0 +1,140 @@ +# new ruby parser from retoo, that should help extracting "#{_('xxx')}", which is needed especially when parsing haml files +# +#!/usr/bin/ruby +# parser/ruby.rb - look for gettext msg strings in ruby files +# Copyright (C) 2009 Reto Schüttel <reto (ät) schuettel (dot) ch> +# You may redistribute it and/or modify it under the same license terms as Ruby. + +require 'rubygems' +require 'ruby_parser' + +module RubyGettextExtractor + extend self + + def parse(file, targets = []) # :nodoc: + content = File.read(file) + parse_string(content, file, targets) + end + + def parse_string(content, file, targets=[]) + # file is just for information in error messages + parser = Extractor.new(file, targets) + parser.run(content) + end + + def target?(file) # :nodoc: + return file =~ /\.rb$/ + end + + class Extractor < RubyParser + def initialize(filename, targets) + @filename = filename + @targets = Hash.new + @results = [] + + targets.each do |a| + k, v = a + # things go wrong if k already exists, but this + # should not happen (according to the gettext doc) + @targets[k] = a + @results << a + end + + super() + end + + def run(content) + # ruby parser has an ugly bug which causes that several \000's take + # ages to parse. This avoids this probelm by stripping them away (they probably wont appear in keys anyway) + # See bug report: http://rubyforge.org/tracker/index.php?func=detail&aid=26898&group_id=439&atid=1778 + safe_content = content.gsub(/\\\d\d\d/, '') + self.parse(safe_content) + return @results + end + + def extract_string(node) + if node.first == :str + return node.last + elsif node.first == :call + type, recv, meth, args = node + + # node has to be in form of "string"+("other_string") + return nil unless recv && meth == :+ + + # descent recurrsivly to determine the 'receiver' of the string concatination + # "foo" + "bar" + baz" is + # ("foo".+("bar")).+("baz") + first_part = extract_string(recv) + + if args.first == :arglist && args.size == 2 + second_part = extract_string(args.last) + + return nil if second_part.nil? + + return first_part.to_s + second_part.to_s + else + raise "uuh?" + end + else + return nil + end + end + + def extract_key(args, seperator) + key = nil + if args.size == 2 + key = extract_string(args.value) + else + # this could be n_("aaa","aaa2",1) + # all strings arguemnts are extracted and joined with \004 or \000 + + arguments = args[1..(-1)] + + res = [] + arguments.each do |a| + str = extract_string(a) + # only add strings + res << str if str + end + + return nil if res.empty? + key = res.join(seperator) + end + + return nil unless key + + key.gsub!("\n", '\n') + key.gsub!("\t", '\t') + key.gsub!("\0", '\0') + + return key + end + + def new_call recv, meth, args = nil + # we dont care if the method is called on a a object + if recv.nil? + if (meth == :_ || meth == :p_ || meth == :N_ || meth == :pgettext || meth == :s_) + key = extract_key(args, "\004") + elsif meth == :n_ + key = extract_key(args, "\000") + else + # skip + end + + if key + res = @targets[key] + + unless res + res = [key] + @results << res + @targets[key] = res + end + + res << "#{@filename}:#{lexer.lineno}" + end + end + + super recv, meth, args + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/string_interpolate_fix.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/string_interpolate_fix.rb new file mode 100644 index 000000000..c919e66df --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/string_interpolate_fix.rb @@ -0,0 +1,20 @@ +needed = "".respond_to?(:html_safe) and + ( + "".html_safe % {:x => '<br/>'} == '<br/>' or + not ("".html_safe % {:x=>'a'}).html_safe? + ) + +if needed + class String + alias :interpolate_without_html_safe :% + + def %(*args) + if args.first.is_a?(Hash) and html_safe? + safe_replacement = Hash[args.first.map{|k,v| [k,ERB::Util.h(v)] }] + interpolate_without_html_safe(safe_replacement).html_safe + else + interpolate_without_html_safe(*args).dup # make sure its not html_safe + end + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/tasks.rb b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/tasks.rb new file mode 100644 index 000000000..b52157a2f --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/tasks.rb @@ -0,0 +1,120 @@ +namespace :gettext do + def load_gettext + require 'gettext' + require 'gettext/utils' + end + + desc "Create mo-files for L10n" + task :pack do + load_gettext + GetText.create_mofiles(true, locale_path, locale_path) + end + + desc "Update pot/po files." + task :find => :environment do + load_gettext + $LOAD_PATH << File.join(File.dirname(__FILE__),'..','..','lib') + require 'gettext_i18n_rails/haml_parser' + + + if GetText.respond_to? :update_pofiles_org + GetText.update_pofiles_org( + text_domain, + files_to_translate, + "version 0.0.1", + :po_root => locale_path, + :msgmerge=>['--sort-output'] + ) + else #we are on a version < 2.0 + puts "install new GetText with gettext:install to gain more features..." + #kill ar parser... + require 'gettext/parser/active_record' + module GetText + module ActiveRecordParser + module_function + def init(x);end + end + end + + #parse files.. (models are simply parsed as ruby files) + GetText.update_pofiles( + text_domain, + files_to_translate, + "version 0.0.1", + locale_path + ) + end + end + + # This is more of an example, ignoring + # the columns/tables that mostly do not need translation. + # This can also be done with GetText::ActiveRecord + # but this crashed too often for me, and + # IMO which column should/should-not be translated does not + # belong into the model + # + # You can get your translations from GetText::ActiveRecord + # by adding this to you gettext:find task + # + # require 'active_record' + # gem "gettext_activerecord", '>=0.1.0' #download and install from github + # require 'gettext_activerecord/parser' + desc "write the model attributes to <locale_path>/model_attributes.rb" + task :store_model_attributes => :environment do + FastGettext.silence_errors + + require 'gettext_i18n_rails/model_attributes_finder' + require 'gettext_i18n_rails/active_record' + + storage_file = "#{locale_path}/model_attributes.rb" + puts "writing model translations to: #{storage_file}" + + ignore_tables = [/^sitemap_/, /_versions$/, 'schema_migrations', 'sessions', 'delayed_jobs'] + GettextI18nRails.store_model_attributes( + :to => storage_file, + :ignore_columns => [/_id$/, 'id', 'type', 'created_at', 'updated_at'], + :ignore_tables => ignore_tables + ) + end + + desc "add a new language" + task :add_language, [:language] => :environment do |_, args| + language = args.language || ENV["LANGUAGE"] + + # Let's do some pre-verification of the environment. + if language.nil? + puts "You need to specify the language to add. Either 'LANGUAGE=eo rake gettext:add_languange' or 'rake gettext:add_languange[eo]'" + next + end + pot = File.join(locale_path, "#{text_domain}.pot") + if !File.exists? pot + puts "You don't have a pot file yet, you probably should run 'rake gettext:find' at least once. Tried '#{pot}'." + next + end + + # Create the directory for the new language. + dir = File.join(locale_path, language) + puts "Creating directory #{dir}" + Dir.mkdir dir + + # Create the po file for the new language. + new_po = File.join(locale_path, language, "#{text_domain}.po") + puts "Initializing #{new_po} from #{pot}." + system "msginit --locale=#{language} --input=#{pot} --output=#{new_po}" + end + + def locale_path + FastGettext.translation_repositories[text_domain].instance_variable_get(:@options)[:path] + rescue + File.join(RAILS_ROOT, "locale") + end + + def text_domain + # if your textdomain is not 'app': require the environment before calling e.g. gettext:find OR add TEXTDOMAIN=my_domain + ENV['TEXTDOMAIN'] || (FastGettext.text_domain rescue nil) || "app" + end + + def files_to_translate + Dir.glob("{app,lib,config,#{locale_path}}/**/*.{rb,erb,haml}") + end +end diff --git a/vendor/plugins/gettext_i18n_rails/lib/tasks/gettext_rails_i18n.rake b/vendor/plugins/gettext_i18n_rails/lib/tasks/gettext_rails_i18n.rake new file mode 100644 index 000000000..540b0c79d --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/lib/tasks/gettext_rails_i18n.rake @@ -0,0 +1 @@ +require File.join(File.dirname(__FILE__), "/../gettext_i18n_rails/tasks") diff --git a/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/action_controller_spec.rb b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/action_controller_spec.rb new file mode 100644 index 000000000..9b12c9fa8 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/action_controller_spec.rb @@ -0,0 +1,40 @@ +require File.expand_path("../spec_helper", File.dirname(__FILE__)) + +FastGettext.silence_errors + +describe ActionController::Base do + before do + #controller + @c = ActionController::Base.new + fake_session = {} + @c.stub!(:session).and_return fake_session + fake_cookies = {} + @c.stub!(:cookies).and_return fake_cookies + @c.params = {} + @c.request = stub(:env => {}) + + #locale + FastGettext.available_locales = nil + FastGettext.locale = 'fr' + FastGettext.available_locales = ['fr','en'] + end + + it "changes the locale" do + @c.params = {:locale=>'en'} + @c.set_gettext_locale + @c.session[:locale].should == 'en' + FastGettext.locale.should == 'en' + end + + it "stays with default locale when none was found" do + @c.set_gettext_locale + @c.session[:locale].should == 'fr' + FastGettext.locale.should == 'fr' + end + + it "reads the locale from the HTTP_ACCEPT_LANGUAGE" do + @c.request.stub!(:env).and_return 'HTTP_ACCEPT_LANGUAGE'=>'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3' + @c.set_gettext_locale + FastGettext.locale.should == 'en' + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb new file mode 100644 index 000000000..aad5aaf42 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb @@ -0,0 +1,83 @@ +# coding: utf-8 +require File.expand_path("../spec_helper", File.dirname(__FILE__)) + +FastGettext.silence_errors + +ActiveRecord::Base.establish_connection({ + :adapter => "sqlite3", + :database => ":memory:", +}) + +ActiveRecord::Schema.define(:version => 1) do + create_table :car_seats, :force=>true do |t| + t.string :seat_color + end + + create_table :parts, :force=>true do |t| + t.string :name + t.references :car_seat + end +end + +class CarSeat < ActiveRecord::Base + validates_presence_of :seat_color, :message=>"translate me" + has_many :parts + accepts_nested_attributes_for :parts +end + +class Part < ActiveRecord::Base + belongs_to :car_seat +end + +describe ActiveRecord::Base do + before do + FastGettext.current_cache = {} + end + + describe :human_name do + it "is translated through FastGettext" do + CarSeat.should_receive(:_).with('car seat').and_return('Autositz') + CarSeat.human_name.should == 'Autositz' + end + end + + describe :human_attribute_name do + it "translates attributes through FastGettext" do + CarSeat.should_receive(:s_).with('CarSeat|Seat color').and_return('Sitz farbe') + CarSeat.human_attribute_name(:seat_color).should == 'Sitz farbe' + end + + it "translates nested attributes through FastGettext" do + CarSeat.should_receive(:s_).with('CarSeat|Parts|Name').and_return('Handle') + CarSeat.human_attribute_name(:"parts.name").should == 'Handle' + end + end + + describe 'error messages' do + let(:model){ + c = CarSeat.new + c.valid? + c + } + + it "translates error messages" do + FastGettext.stub!(:current_repository).and_return('translate me'=>"Übersetz mich!") + FastGettext._('translate me').should == "Übersetz mich!" + model.errors.on(:seat_color).should == "Übersetz mich!" + end + + it "translates scoped error messages" do + pending 'scope is no longer added in 3.x' if ActiveRecord::VERSION::MAJOR >= 3 + FastGettext.stub!(:current_repository).and_return('activerecord.errors.translate me'=>"Übersetz mich!") + FastGettext._('activerecord.errors.translate me').should == "Übersetz mich!" + model.errors.on(:seat_color).should == "Übersetz mich!" + end + + it "translates error messages with %{fn}" do + pending + FastGettext.stub!(:current_repository).and_return('translate me'=>"Übersetz %{fn} mich!") + FastGettext._('translate me').should == "Übersetz %{fn} mich!" + model.errors.on(:seat_color).should == "Übersetz car_seat mich!" + end + end +end diff --git a/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb new file mode 100644 index 000000000..e0df1e725 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb @@ -0,0 +1,46 @@ +require File.expand_path("../spec_helper", File.dirname(__FILE__)) + +describe GettextI18nRails::Backend do + it "redirects calls to another I18n backend" do + subject.backend.should_receive(:xxx).with(1,2) + subject.xxx(1,2) + end + + describe :available_locales do + it "maps them to FastGettext" do + FastGettext.should_receive(:available_locales).and_return [:xxx] + subject.available_locales.should == [:xxx] + end + + it "and returns an empty array when FastGettext.available_locales is nil" do + FastGettext.should_receive(:available_locales).and_return nil + subject.available_locales.should == [] + end + end + + describe :translate do + it "uses gettext when the key is translatable" do + FastGettext.stub(:current_repository).and_return 'xy.z.u'=>'a' + subject.translate('xx','u',:scope=>['xy','z']).should == 'a' + end + + it "interpolates options" do + FastGettext.stub(:current_repository).and_return 'ab.c'=>'a%{a}b' + subject.translate('xx','c',:scope=>['ab'], :a => 'X').should == 'aXb' + end + + it "can translate with gettext using symbols" do + FastGettext.stub(:current_repository).and_return 'xy.z.v'=>'a' + subject.translate('xx',:v ,:scope=>['xy','z']).should == 'a' + end + + it "can translate with gettext using a flat scope" do + FastGettext.stub(:current_repository).and_return 'xy.z.x'=>'a' + subject.translate('xx',:x ,:scope=>'xy.z').should == 'a' + end + + it "uses the super when the key is not translatable" do + lambda{subject.translate('xx','y',:scope=>['xy','z'])}.should raise_error(I18n::MissingTranslationData) + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb new file mode 100644 index 000000000..c437699e7 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb @@ -0,0 +1,32 @@ +require File.expand_path("../spec_helper", File.dirname(__FILE__)) +require 'gettext_i18n_rails/string_interpolate_fix' + +describe "String#%" do + it "is not safe if it was not safe" do + result = ("<br/>%{x}" % {:x => 'a'}) + result.should == '<br/>a' + result.html_safe?.should == false + end + + it "stays safe if it was safe" do + result = ("<br/>%{x}".html_safe % {:x => 'a'}) + result.should == '<br/>a' + result.html_safe?.should == true + end + + it "escapes unsafe added to safe" do + result = ("<br/>%{x}".html_safe % {:x => '<br/>'}) + result.should == '<br/><br/>' + result.html_safe?.should == true + end + + it "does not escape unsafe if it was unsafe" do + result = ("<br/>%{x}" % {:x => '<br/>'}) + result.should == '<br/><br/>' + result.html_safe?.should == false + end + + it "does not break array replacement" do + "%ssd" % ['a'].should == "asd" + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb new file mode 100644 index 000000000..3688d8b10 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb @@ -0,0 +1,84 @@ +require File.expand_path("spec_helper", File.dirname(__FILE__)) + +FastGettext.silence_errors + +describe GettextI18nRails do + before do + GettextI18nRails.translations_are_html_safe = nil + end + + it "extends all classes with fast_gettext" do + _('test') + end + + describe 'translations_are_html_safe' do + before do + GettextI18nRails.translations_are_html_safe = nil + end + + it "makes translations not html_safe by default" do + _('x').html_safe?.should == false + s_('x').html_safe?.should == false + n_('x','y',2).html_safe?.should == false + String._('x').html_safe?.should == false + String.s_('x').html_safe?.should == false + String.n_('x','y',2).html_safe?.should == false + end + + it "makes instance translations html_safe when wanted" do + GettextI18nRails.translations_are_html_safe = true + _('x').html_safe?.should == true + s_('x').html_safe?.should == true + n_('x','y',2).html_safe?.should == true + end + + it "makes class translations html_safe when wanted" do + GettextI18nRails.translations_are_html_safe = true + String._('x').html_safe?.should == true + String.s_('x').html_safe?.should == true + String.n_('x','y',2).html_safe?.should == true + end + + it "does not make everything html_safe" do + 'x'.html_safe?.should == false + end + end + + it "sets up out backend" do + I18n.backend.is_a?(GettextI18nRails::Backend).should be_true + end + + it "has a VERSION" do + GettextI18nRails::VERSION.should =~ /^\d+\.\d+\.\d+$/ + end + + describe 'FastGettext I18n interaction' do + before do + FastGettext.available_locales = nil + FastGettext.locale = 'de' + end + + it "links FastGettext with I18n locale" do + FastGettext.locale = 'xx' + I18n.locale.should == :xx + end + + it "does not set an not-accepted locale to I18n.locale" do + FastGettext.available_locales = ['de'] + FastGettext.locale = 'xx' + I18n.locale.should == :de + end + + it "links I18n.locale and FastGettext.locale" do + I18n.locale = :yy + FastGettext.locale.should == 'yy' + end + + it "does not set a non-available locale though I18n.locale" do + FastGettext.available_locales = ['de'] + I18n.locale = :xx + FastGettext.locale.should == 'de' + I18n.locale.should == :de + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb b/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb new file mode 100644 index 000000000..f8002b766 --- /dev/null +++ b/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb @@ -0,0 +1,17 @@ +require 'rubygems' +if ENV['VERSION'] + puts "running VERSION #{ENV['VERSION']}" + gem 'actionpack', ENV['VERSION'] + gem 'activerecord', ENV['VERSION'] + gem 'activesupport', ENV['VERSION'] + gem 'actionmailer', ENV['VERSION'] +end + +$LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__)) + +require 'active_support' +require 'active_record' +require 'action_controller' +require 'action_mailer' +require 'fast_gettext' +require 'gettext_i18n_rails'
\ No newline at end of file |