diff options
Diffstat (limited to 'vendor/plugins/gettext_i18n_rails/lib')
13 files changed, 570 insertions, 0 deletions
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") |