nulogy-gettext_i18n_rails 0.4.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +16 -0
- data/Gemfile.lock +126 -0
- data/Rakefile +24 -0
- data/Readme.md +226 -0
- data/VERSION +1 -0
- data/gettext_i18n_rails.gemspec +65 -0
- data/init.rb +14 -0
- data/lib/gettext_i18n_rails.rb +33 -0
- data/lib/gettext_i18n_rails/action_controller.rb +8 -0
- data/lib/gettext_i18n_rails/active_record.rb +19 -0
- data/lib/gettext_i18n_rails/backend.rb +67 -0
- data/lib/gettext_i18n_rails/base_parser.rb +41 -0
- data/lib/gettext_i18n_rails/haml_parser.rb +15 -0
- data/lib/gettext_i18n_rails/hamlet_parser.rb +16 -0
- data/lib/gettext_i18n_rails/html_safe_translations.rb +29 -0
- data/lib/gettext_i18n_rails/i18n_hacks.rb +25 -0
- data/lib/gettext_i18n_rails/model_attributes_finder.rb +108 -0
- data/lib/gettext_i18n_rails/railtie.rb +22 -0
- data/lib/gettext_i18n_rails/ruby_gettext_extractor.rb +144 -0
- data/lib/gettext_i18n_rails/slim_parser.rb +15 -0
- data/lib/gettext_i18n_rails/string_interpolate_fix.rb +20 -0
- data/lib/gettext_i18n_rails/tasks.rb +127 -0
- data/lib/tasks/gettext_rails_i18n.rake +1 -0
- data/spec/gettext_i18n_rails/action_controller_spec.rb +54 -0
- data/spec/gettext_i18n_rails/active_record_spec.rb +85 -0
- data/spec/gettext_i18n_rails/backend_spec.rb +56 -0
- data/spec/gettext_i18n_rails/haml_parser_spec.rb +39 -0
- data/spec/gettext_i18n_rails/hamlet_parser_spec.rb +33 -0
- data/spec/gettext_i18n_rails/slim_parser_spec.rb +40 -0
- data/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb +32 -0
- data/spec/gettext_i18n_rails_spec.rb +84 -0
- data/spec/spec_helper.rb +39 -0
- metadata +110 -0
data/init.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
begin
|
2
|
+
require 'config/initializers/session_store'
|
3
|
+
rescue LoadError
|
4
|
+
# weird bug, when run with rake rails reports error that session
|
5
|
+
# store is not configured, this fixes it somewhat...
|
6
|
+
end
|
7
|
+
|
8
|
+
if Rails::VERSION::MAJOR > 2
|
9
|
+
require 'gettext_i18n_rails'
|
10
|
+
else
|
11
|
+
#requires fast_gettext to be present.
|
12
|
+
#We give rails a chance to install it using rake gems:install, by loading it later.
|
13
|
+
config.after_initialize { require 'gettext_i18n_rails' }
|
14
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module GettextI18nRails
|
2
|
+
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
|
3
|
+
|
4
|
+
extend self
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'fast_gettext'
|
8
|
+
if Gem::Version.new(FastGettext::VERSION) < Gem::Version.new("0.4.8")
|
9
|
+
raise "Please upgrade fast_gettext"
|
10
|
+
end
|
11
|
+
|
12
|
+
# include translations into all the places it needs to go...
|
13
|
+
Object.send(:include, FastGettext::Translation)
|
14
|
+
|
15
|
+
# make translations html_safe if possible and wanted
|
16
|
+
if "".respond_to?(:html_safe?)
|
17
|
+
require 'gettext_i18n_rails/html_safe_translations'
|
18
|
+
Object.send(:include, GettextI18nRails::HtmlSafeTranslations)
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'gettext_i18n_rails/backend'
|
22
|
+
I18n.backend = GettextI18nRails::Backend.new
|
23
|
+
|
24
|
+
require 'gettext_i18n_rails/i18n_hacks'
|
25
|
+
|
26
|
+
require 'gettext_i18n_rails/active_record'
|
27
|
+
# If configuration via Railties is not available force activerecord extensions
|
28
|
+
if not defined?(Rails::Railtie) and defined?(ActiveRecord)
|
29
|
+
ActiveRecord::Base.extend GettextI18nRails::ActiveRecord
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'gettext_i18n_rails/action_controller' if defined?(ActionController) # so that bundle console can work in a rails project
|
33
|
+
require 'gettext_i18n_rails/railtie'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class ActionController::Base
|
2
|
+
def set_gettext_locale
|
3
|
+
requested_locale = params[:locale] || session[:locale] || cookies[:locale] || request.env['HTTP_ACCEPT_LANGUAGE'] || I18n.default_locale
|
4
|
+
locale = FastGettext.set_locale(requested_locale)
|
5
|
+
session[:locale] = locale
|
6
|
+
I18n.locale = locale # some weird overwriting in action-controller makes this necessary ... see I18nProxy
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GettextI18nRails::ActiveRecord
|
2
|
+
# CarDealer.sales_count -> s_('CarDealer|Sales count') -> 'Sales count' if no translation was found
|
3
|
+
def human_attribute_name(attribute, *args)
|
4
|
+
s_(gettext_translation_for_attribute_name(attribute))
|
5
|
+
end
|
6
|
+
|
7
|
+
# CarDealer -> _('car dealer')
|
8
|
+
def human_name(*args)
|
9
|
+
_(self.human_name_without_translation)
|
10
|
+
end
|
11
|
+
|
12
|
+
def human_name_without_translation
|
13
|
+
self.to_s.underscore.gsub('_',' ')
|
14
|
+
end
|
15
|
+
|
16
|
+
def gettext_translation_for_attribute_name(attribute)
|
17
|
+
"#{self}|#{attribute.to_s.split('.').map! {|a| a.humanize }.join('|')}"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module GettextI18nRails
|
2
|
+
#translates i18n calls to gettext calls
|
3
|
+
class Backend
|
4
|
+
@@translate_defaults = true
|
5
|
+
cattr_accessor :translate_defaults
|
6
|
+
attr_accessor :backend
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
self.backend = I18n::Backend::Simple.new(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def available_locales
|
13
|
+
FastGettext.available_locales || []
|
14
|
+
end
|
15
|
+
|
16
|
+
def translate(locale, key, options)
|
17
|
+
if gettext_key = gettext_key(key, options)
|
18
|
+
translation = FastGettext._(gettext_key)
|
19
|
+
interpolate(translation, options)
|
20
|
+
else
|
21
|
+
backend.translate locale, key, options
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args)
|
26
|
+
backend.send(method, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def gettext_key(key, options)
|
32
|
+
flat_key = flatten_key key, options
|
33
|
+
if FastGettext.key_exist?(flat_key)
|
34
|
+
flat_key
|
35
|
+
elsif self.class.translate_defaults
|
36
|
+
[*options[:default]].each do |default|
|
37
|
+
#try the scoped(more specific) key first e.g. 'activerecord.errors.my custom message'
|
38
|
+
flat_key = flatten_key default, options
|
39
|
+
return flat_key if FastGettext.key_exist?(flat_key)
|
40
|
+
|
41
|
+
#try the short key thereafter e.g. 'my custom message'
|
42
|
+
return default if FastGettext.key_exist?(default)
|
43
|
+
end
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def interpolate(string, values)
|
49
|
+
if string.respond_to?(:%)
|
50
|
+
reserved_keys = if defined?(I18n::RESERVED_KEYS) # rails 3+
|
51
|
+
I18n::RESERVED_KEYS
|
52
|
+
else
|
53
|
+
I18n::Backend::Base::RESERVED_KEYS
|
54
|
+
end
|
55
|
+
|
56
|
+
string % values.except(*reserved_keys)
|
57
|
+
else
|
58
|
+
string
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def flatten_key key, options
|
63
|
+
scope = [*(options[:scope] || [])]
|
64
|
+
scope.empty? ? key.to_s : "#{scope*'.'}.#{key}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'gettext/utils'
|
2
|
+
begin
|
3
|
+
require 'gettext/tools/rgettext'
|
4
|
+
rescue LoadError #version prior to 2.0
|
5
|
+
require 'gettext/rgettext'
|
6
|
+
end
|
7
|
+
|
8
|
+
module GettextI18nRails
|
9
|
+
class BaseParser
|
10
|
+
def self.target?(file)
|
11
|
+
File.extname(file) == ".#{extension}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parse(file, msgids = [])
|
15
|
+
return msgids unless load_library
|
16
|
+
code = convert_to_code(File.read(file))
|
17
|
+
RubyGettextExtractor.parse_string(code, file, msgids)
|
18
|
+
rescue Racc::ParseError => e
|
19
|
+
$stderr.puts "file ignored: ruby_parser cannot read #{extension} files with 1.9 syntax --- (#{e.message})"
|
20
|
+
return msgids
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.load_library
|
24
|
+
return true if @library_loaded
|
25
|
+
|
26
|
+
begin
|
27
|
+
require "#{::Rails.root.to_s}/vendor/plugins/#{extension}/lib/#{extension}"
|
28
|
+
rescue LoadError
|
29
|
+
begin
|
30
|
+
require extension # From gem
|
31
|
+
rescue LoadError
|
32
|
+
puts "A #{extension} file was found, but #{extension} library could not be found, so nothing will be parsed..."
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'gettext_i18n_rails/ruby_gettext_extractor'
|
38
|
+
@library_loaded = true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'gettext_i18n_rails/base_parser'
|
2
|
+
|
3
|
+
module GettextI18nRails
|
4
|
+
class HamlParser < BaseParser
|
5
|
+
def self.extension
|
6
|
+
"haml"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.convert_to_code(text)
|
10
|
+
Haml::Engine.new(text).precompiled()
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
GetText::RGetText.add_parser(GettextI18nRails::HamlParser)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'gettext_i18n_rails/base_parser'
|
2
|
+
|
3
|
+
module GettextI18nRails
|
4
|
+
class HamletParser < BaseParser
|
5
|
+
def self.extension
|
6
|
+
"hamlet"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.convert_to_code(text)
|
10
|
+
Hamlet::Engine.new.call(text)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
GetText::RGetText.add_parser(GettextI18nRails::HamletParser)
|
16
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module GettextI18nRails
|
2
|
+
mattr_accessor :translations_are_html_safe
|
3
|
+
|
4
|
+
module HtmlSafeTranslations
|
5
|
+
# also make available on class methods
|
6
|
+
def self.included(base)
|
7
|
+
base.extend self
|
8
|
+
end
|
9
|
+
|
10
|
+
def _(*args)
|
11
|
+
html_safe_if_wanted super
|
12
|
+
end
|
13
|
+
|
14
|
+
def n_(*args)
|
15
|
+
html_safe_if_wanted super
|
16
|
+
end
|
17
|
+
|
18
|
+
def s_(*args)
|
19
|
+
html_safe_if_wanted super
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def html_safe_if_wanted(text)
|
25
|
+
return text unless GettextI18nRails.translations_are_html_safe
|
26
|
+
text.to_s.html_safe
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
I18n::Config # autoload
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
class Config
|
5
|
+
def locale
|
6
|
+
FastGettext.locale.to_sym
|
7
|
+
end
|
8
|
+
|
9
|
+
def locale=(new_locale)
|
10
|
+
FastGettext.locale=(new_locale)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# backport I18n.with_locale if it does not exist
|
15
|
+
# Executes block with given I18n.locale set.
|
16
|
+
def self.with_locale(tmp_locale = nil)
|
17
|
+
if tmp_locale
|
18
|
+
current_locale = self.locale
|
19
|
+
self.locale = tmp_locale
|
20
|
+
end
|
21
|
+
yield
|
22
|
+
ensure
|
23
|
+
self.locale = current_locale if tmp_locale
|
24
|
+
end unless defined? I18n.with_locale
|
25
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module GettextI18nRails
|
2
|
+
#write all found models/columns to a file where GetTexts ruby parser can find them
|
3
|
+
def store_model_attributes(options)
|
4
|
+
file = options[:to] || 'locale/model_attributes.rb'
|
5
|
+
begin
|
6
|
+
File.open(file,'w') do |f|
|
7
|
+
f.puts "#DO NOT MODIFY! AUTOMATICALLY GENERATED FILE!"
|
8
|
+
ModelAttributesFinder.new.find(options).each do |table_name,column_names|
|
9
|
+
#model name
|
10
|
+
model = table_name_to_namespaced_model(table_name)
|
11
|
+
if model == nil
|
12
|
+
# Some tables are not models, for example: translation tables created by globalize2.
|
13
|
+
puts "[Warning] Model not found for table '#{table_name}'"
|
14
|
+
next
|
15
|
+
end
|
16
|
+
f.puts("_('#{model.human_name_without_translation}')")
|
17
|
+
|
18
|
+
#all columns namespaced under the model
|
19
|
+
column_names.each do |attribute|
|
20
|
+
translation = model.gettext_translation_for_attribute_name(attribute)
|
21
|
+
f.puts("_('#{translation}')")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
f.puts "#DO NOT MODIFY! AUTOMATICALLY GENERATED FILE!"
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
puts "[Error] Attribute extraction failed. Removing incomplete file (#{file})"
|
28
|
+
File.delete(file)
|
29
|
+
raise
|
30
|
+
end
|
31
|
+
end
|
32
|
+
module_function :store_model_attributes
|
33
|
+
|
34
|
+
class ModelAttributesFinder
|
35
|
+
# options:
|
36
|
+
# :ignore_tables => ['cars',/_settings$/,...]
|
37
|
+
# :ignore_columns => ['id',/_id$/,...]
|
38
|
+
# current connection ---> {'cars'=>['model_name','type'],...}
|
39
|
+
def find(options)
|
40
|
+
found = Hash.new([])
|
41
|
+
|
42
|
+
connection = ::ActiveRecord::Base.connection
|
43
|
+
connection.tables.each do |table_name|
|
44
|
+
next if ignored?(table_name,options[:ignore_tables])
|
45
|
+
connection.columns(table_name).each do |column|
|
46
|
+
found[table_name] += [column.name] unless ignored?(column.name,options[:ignore_columns])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
found
|
51
|
+
end
|
52
|
+
|
53
|
+
def ignored?(name,patterns)
|
54
|
+
return false unless patterns
|
55
|
+
patterns.detect{|p|p.to_s==name.to_s or (p.is_a?(Regexp) and name=~p)}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
# Tries to find the model class corresponding to specified table name.
|
61
|
+
# Takes into account that the model can be defined in a namespace.
|
62
|
+
# Searches only up to one level deep - won't find models nested in two
|
63
|
+
# or more modules.
|
64
|
+
#
|
65
|
+
# Note that if we allow namespaces, the conversion can be ambiguous, i.e.
|
66
|
+
# if the table is named "aa_bb_cc" and AaBbCc, Aa::BbCc and AaBb::Cc are
|
67
|
+
# all defined there's no absolute rule that tells us which one to use.
|
68
|
+
# This method prefers the less nested one and, if there are two at
|
69
|
+
# the same level, the one with shorter module name.
|
70
|
+
def table_name_to_namespaced_model(table_name)
|
71
|
+
# First assume that there are no namespaces
|
72
|
+
model = to_class(table_name.singularize.camelcase)
|
73
|
+
return model if model != nil
|
74
|
+
|
75
|
+
# If you were wrong, assume that the model is in a namespace.
|
76
|
+
# Iterate over the underscores and try to substitute each of them
|
77
|
+
# for a slash that camelcase() replaces with the scope operator (::).
|
78
|
+
underscore_position = table_name.index('_')
|
79
|
+
while underscore_position != nil
|
80
|
+
namespaced_table_name = table_name.dup
|
81
|
+
namespaced_table_name[underscore_position] = '/'
|
82
|
+
model = to_class(namespaced_table_name.singularize.camelcase)
|
83
|
+
return model if model != nil
|
84
|
+
|
85
|
+
underscore_position = table_name.index('_', underscore_position + 1)
|
86
|
+
end
|
87
|
+
|
88
|
+
# The model either is not defined or is buried more than one level
|
89
|
+
# deep in a module hierarchy
|
90
|
+
return nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# Checks if there is a class of specified name and if so, returns
|
94
|
+
# the class object. Otherwise returns nil.
|
95
|
+
def to_class(name)
|
96
|
+
# I wanted to use Module.const_defined?() here to avoid relying
|
97
|
+
# on exceptions for normal program flow but it's of no use.
|
98
|
+
# If class autoloading is enabled, the constant may be undefined
|
99
|
+
# but turn out to be present when we actually try to use it.
|
100
|
+
begin
|
101
|
+
constant = name.constantize
|
102
|
+
rescue NameError
|
103
|
+
return nil
|
104
|
+
end
|
105
|
+
|
106
|
+
return constant.is_a?(Class) ? constant : nil
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# add rake tasks if we are inside Rails
|
2
|
+
if defined?(Rails::Railtie)
|
3
|
+
module GettextI18nRails
|
4
|
+
class Railtie < ::Rails::Railtie
|
5
|
+
config.gettext_i18n_rails = ActiveSupport::OrderedOptions.new
|
6
|
+
config.gettext_i18n_rails.msgmerge = %w[--sort-output --no-location --no-wrap]
|
7
|
+
config.gettext_i18n_rails.use_for_active_record_attributes = true
|
8
|
+
|
9
|
+
rake_tasks do
|
10
|
+
require 'gettext_i18n_rails/tasks'
|
11
|
+
end
|
12
|
+
|
13
|
+
config.after_initialize do |app|
|
14
|
+
if app.config.gettext_i18n_rails.use_for_active_record_attributes
|
15
|
+
ActiveSupport.on_load :active_record do
|
16
|
+
extend GettextI18nRails::ActiveRecord
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# new ruby parser from retoo, that should help extracting "#{_('xxx')}", which is needed especially when parsing haml files
|
2
|
+
#
|
3
|
+
#!/usr/bin/ruby
|
4
|
+
# parser/ruby.rb - look for gettext msg strings in ruby files
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'ruby_parser'
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'gettext/tools/rgettext'
|
11
|
+
rescue LoadError #version prior to 2.0
|
12
|
+
require 'gettext/rgettext'
|
13
|
+
end
|
14
|
+
|
15
|
+
module RubyGettextExtractor
|
16
|
+
extend self
|
17
|
+
|
18
|
+
def parse(file, targets = []) # :nodoc:
|
19
|
+
content = File.read(file)
|
20
|
+
parse_string(content, file, targets)
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_string(content, file, targets=[])
|
24
|
+
# file is just for information in error messages
|
25
|
+
parser = Extractor.new(file, targets)
|
26
|
+
parser.run(content)
|
27
|
+
end
|
28
|
+
|
29
|
+
def target?(file) # :nodoc:
|
30
|
+
return file =~ /\.rb$/
|
31
|
+
end
|
32
|
+
|
33
|
+
class Extractor < RubyParser
|
34
|
+
def initialize(filename, targets)
|
35
|
+
@filename = filename
|
36
|
+
@targets = Hash.new
|
37
|
+
@results = []
|
38
|
+
|
39
|
+
targets.each do |a|
|
40
|
+
k, v = a
|
41
|
+
# things go wrong if k already exists, but this
|
42
|
+
# should not happen (according to the gettext doc)
|
43
|
+
@targets[k] = a
|
44
|
+
@results << a
|
45
|
+
end
|
46
|
+
|
47
|
+
super()
|
48
|
+
end
|
49
|
+
|
50
|
+
def run(content)
|
51
|
+
# ruby parser has an ugly bug which causes that several \000's take
|
52
|
+
# ages to parse. This avoids this probelm by stripping them away (they probably wont appear in keys anyway)
|
53
|
+
# See bug report: http://rubyforge.org/tracker/index.php?func=detail&aid=26898&group_id=439&atid=1778
|
54
|
+
safe_content = content.gsub(/\\\d\d\d/, '')
|
55
|
+
self.parse(safe_content)
|
56
|
+
return @results
|
57
|
+
end
|
58
|
+
|
59
|
+
def extract_string(node)
|
60
|
+
if node.first == :str
|
61
|
+
return node.last
|
62
|
+
elsif node.first == :call
|
63
|
+
type, recv, meth, args = node
|
64
|
+
|
65
|
+
# node has to be in form of "string"+("other_string")
|
66
|
+
return nil unless recv && meth == :+
|
67
|
+
|
68
|
+
# descent recurrsivly to determine the 'receiver' of the string concatination
|
69
|
+
# "foo" + "bar" + baz" is
|
70
|
+
# ("foo".+("bar")).+("baz")
|
71
|
+
first_part = extract_string(recv)
|
72
|
+
|
73
|
+
if args.first == :arglist && args.size == 2
|
74
|
+
second_part = extract_string(args.last)
|
75
|
+
|
76
|
+
return nil if second_part.nil?
|
77
|
+
|
78
|
+
return first_part.to_s + second_part.to_s
|
79
|
+
else
|
80
|
+
raise "uuh?"
|
81
|
+
end
|
82
|
+
else
|
83
|
+
return nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def extract_key(args, seperator)
|
88
|
+
key = nil
|
89
|
+
if args.size == 2
|
90
|
+
key = extract_string(args.value)
|
91
|
+
else
|
92
|
+
# this could be n_("aaa","aaa2",1)
|
93
|
+
# all strings arguemnts are extracted and joined with \004 or \000
|
94
|
+
|
95
|
+
arguments = args[1..(-1)]
|
96
|
+
|
97
|
+
res = []
|
98
|
+
arguments.each do |a|
|
99
|
+
str = extract_string(a)
|
100
|
+
# only add strings
|
101
|
+
res << str if str
|
102
|
+
end
|
103
|
+
|
104
|
+
return nil if res.empty?
|
105
|
+
key = res.join(seperator)
|
106
|
+
end
|
107
|
+
|
108
|
+
return nil unless key
|
109
|
+
|
110
|
+
key.gsub!("\n", '\n')
|
111
|
+
key.gsub!("\t", '\t')
|
112
|
+
key.gsub!("\0", '\0')
|
113
|
+
|
114
|
+
return key
|
115
|
+
end
|
116
|
+
|
117
|
+
def new_call recv, meth, args = nil
|
118
|
+
# we dont care if the method is called on a a object
|
119
|
+
if recv.nil?
|
120
|
+
if (meth == :_ || meth == :p_ || meth == :N_ || meth == :pgettext || meth == :s_)
|
121
|
+
key = extract_key(args, "\004")
|
122
|
+
elsif meth == :n_
|
123
|
+
key = extract_key(args, "\000")
|
124
|
+
else
|
125
|
+
# skip
|
126
|
+
end
|
127
|
+
|
128
|
+
if key
|
129
|
+
res = @targets[key]
|
130
|
+
|
131
|
+
unless res
|
132
|
+
res = [key]
|
133
|
+
@results << res
|
134
|
+
@targets[key] = res
|
135
|
+
end
|
136
|
+
|
137
|
+
res << "#{@filename}:#{lexer.lineno}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
super recv, meth, args
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|