rich_i18n 1.0.3

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.
Files changed (44) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGELOG +19 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.textile +269 -0
  5. data/Rakefile +42 -0
  6. data/VERSION +1 -0
  7. data/init.rb +1 -0
  8. data/install.rb +1 -0
  9. data/lib/rich/i18n.rb +11 -0
  10. data/lib/rich/i18n/actionpack.rb +4 -0
  11. data/lib/rich/i18n/actionpack/action_controller/dispatcher.rb +12 -0
  12. data/lib/rich/i18n/actionpack/action_view/base.rb +13 -0
  13. data/lib/rich/i18n/actionpack/action_view/sanitizor.rb +61 -0
  14. data/lib/rich/i18n/core.rb +8 -0
  15. data/lib/rich/i18n/core/array.rb +8 -0
  16. data/lib/rich/i18n/core/array/merging.rb +29 -0
  17. data/lib/rich/i18n/core/enriched_string.rb +28 -0
  18. data/lib/rich/i18n/core/enumerable/methods.rb +16 -0
  19. data/lib/rich/i18n/core/erb.rb +6 -0
  20. data/lib/rich/i18n/core/erb/output.rb +22 -0
  21. data/lib/rich/i18n/core/hash.rb +6 -0
  22. data/lib/rich/i18n/core/nil_class.rb +8 -0
  23. data/lib/rich/i18n/core/object.rb +6 -0
  24. data/lib/rich/i18n/core/object/output.rb +20 -0
  25. data/lib/rich/i18n/core/string.rb +10 -0
  26. data/lib/rich/i18n/core/string/enrichments.rb +68 -0
  27. data/lib/rich/i18n/core/string/inflections.rb +42 -0
  28. data/lib/rich/i18n/core/string/internationalization.rb +82 -0
  29. data/lib/rich/i18n/core/symbol.rb +6 -0
  30. data/lib/rich/i18n/core/symbol/internationalization.rb +16 -0
  31. data/lib/rich/i18n/engine.rb +31 -0
  32. data/lib/rich/i18n/formtastic.rb +51 -0
  33. data/lib/rich_i18n.rb +5 -0
  34. data/locales/nl.yml +14 -0
  35. data/rails/init.rb +1 -0
  36. data/tasks/rich_i18n_tasks.rake +11 -0
  37. data/test/core/string/inflections_test.rb +42 -0
  38. data/test/core/string/internationalization_test.rb +23 -0
  39. data/test/engine_test.rb +20 -0
  40. data/test/locales/nl/internationalization_test.rb +47 -0
  41. data/test/setup.rb +14 -0
  42. data/test/test_helper.rb +5 -0
  43. data/uninstall.rb +1 -0
  44. metadata +136 -0
@@ -0,0 +1,8 @@
1
+
2
+ (required_files = %w(object string enriched_string)).each do |file|
3
+ require "rich/i18n/core/#{file}"
4
+ end
5
+
6
+ Dir[File.join(File.dirname(__FILE__), "core", "*.rb")].each do |file|
7
+ require file unless required_files.include?(File.basename file, ".rb")
8
+ end
@@ -0,0 +1,8 @@
1
+
2
+ require "rich/i18n/core/enumerable/methods"
3
+ require "rich/i18n/core/array/merging"
4
+
5
+ class Array
6
+ include Rich::I18n::Core::Enumerable::Methods
7
+ include Rich::I18n::Core::Array::Merging
8
+ end
@@ -0,0 +1,29 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module Array
6
+ module Merging
7
+
8
+ def self.included(base)
9
+ base.class_eval do
10
+ alias_method_chain :join, :rich_i18n
11
+ end
12
+ end
13
+
14
+ def join_with_rich_i18n(sep = "")
15
+ if size == 1 && first.is_a?(EnrichedString)
16
+ first
17
+ else
18
+ merged_strings = dup
19
+ result = join_without_rich_i18n(sep)
20
+ result.merged_strings = merged_strings
21
+ result
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ class EnrichedString < ::String
6
+
7
+ def initialize(s = "", meta_data = nil)
8
+ super s
9
+ @meta_data = meta_data || (s.meta_data.dup unless (s.meta_data.nil? rescue true)) || {}
10
+ end
11
+
12
+ def initialize_copy_with_rich_i18n(s)
13
+ result = super(s)
14
+ result.meta_data = self.meta_data.dup
15
+ end
16
+
17
+ def to_es
18
+ @meta_data.filled? and ::Rich::I18n::Engine.can_enrich_output? ?
19
+ "<i18n #{@meta_data.collect{|k, v| "data-#{k}=#{v.inspect}"}.join(" ")}>#{to_s}</i18n>" :
20
+ to_s
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ EnrichedString = Rich::I18n::Core::EnrichedString
@@ -0,0 +1,16 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module Enumerable
6
+ module Methods
7
+
8
+ def filled?
9
+ !empty?
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "rich/i18n/core/erb/output"
3
+
4
+ class ERB::Compiler::Buffer
5
+ include Rich::I18n::Core::ERB::Output
6
+ end
@@ -0,0 +1,22 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module ERB
6
+ module Output
7
+
8
+ def self.included(base)
9
+ base.class_eval do
10
+ alias_method_chain :push, :rich_i18n
11
+ end
12
+ end
13
+
14
+ def push_with_rich_i18n(cmd)
15
+ push_without_rich_i18n cmd.match(/^#{@compiler.insert_cmd}\(\(.*\)\.to_s\)$/) ? cmd.gsub(/to_s\)$/, "to_output)") : cmd
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "rich/i18n/core/enumerable/methods"
3
+
4
+ class Hash
5
+ include Rich::I18n::Core::Enumerable::Methods
6
+ end
@@ -0,0 +1,8 @@
1
+
2
+ class NilClass
3
+
4
+ def filled?
5
+ false
6
+ end
7
+
8
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "rich/i18n/core/object/output"
3
+
4
+ class Object
5
+ include Rich::I18n::Core::Object::Output
6
+ end
@@ -0,0 +1,20 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module Object
6
+ module Output
7
+
8
+ def to_output
9
+ to_es
10
+ end
11
+
12
+ def to_es
13
+ to_s
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+
2
+ require "rich/i18n/core/string/inflections"
3
+ require "rich/i18n/core/string/internationalization"
4
+ require "rich/i18n/core/string/enrichments"
5
+
6
+ class String
7
+ include Rich::I18n::Core::String::Inflections
8
+ include Rich::I18n::Core::String::Internationalization
9
+ include Rich::I18n::Core::String::Enrichments
10
+ end
@@ -0,0 +1,68 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module String
6
+ module Enrichments
7
+
8
+ # TODO: override String interpolation (e.g. "foo #{"bar".t}")
9
+
10
+ def self.included(base)
11
+ base.class_eval do
12
+ alias_method :add_without_rich_i18n, :+
13
+ alias_method :+, :add_with_rich_i18n
14
+ alias_method_chain :concat, :rich_i18n
15
+ undef_method :<<
16
+ alias_method :<<, :concat_with_rich_i18n
17
+
18
+ alias_method_chain :initialize_copy, :rich_i18n
19
+
20
+ attr_accessor :meta_data
21
+ attr_accessor :merged_strings
22
+ end
23
+ end
24
+
25
+ def initialize_copy_with_rich_i18n(s)
26
+ result = initialize_copy_without_rich_i18n(s)
27
+ result.merged_strings = self.merged_strings.try :dup
28
+ end
29
+
30
+ def add_with_rich_i18n(other)
31
+ strings, result = self.merged_strings.try(:dup) || [], add_without_rich_i18n(other)
32
+
33
+ if (result.merged_strings = strings).empty?
34
+ result.merged_strings << self.dup
35
+ end
36
+ unless other.empty?
37
+ result.merged_strings << other
38
+ end
39
+
40
+ result
41
+ end
42
+
43
+ def concat_with_rich_i18n(other_or_fixnum)
44
+ string, result = self.dup, concat_without_rich_i18n(other_or_fixnum)
45
+
46
+ if (result.merged_strings ||= []).empty? and !string.empty?
47
+ result.merged_strings << string
48
+ end
49
+ result.merged_strings << other_or_fixnum.dup unless other_or_fixnum.empty?
50
+
51
+ result
52
+ end
53
+
54
+ def enriched_string?
55
+ is_a?(EnrichedString) or (merged_strings || []).any?(&:enriched_string?)
56
+ end
57
+
58
+ def to_output
59
+ merged_strings.blank? ?
60
+ to_es :
61
+ merged_strings.collect(&:to_output).join
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,42 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module String
6
+ module Inflections
7
+
8
+ # -- start FIXME: these methods are also defined in rich_pluralization
9
+
10
+ def upcase_first
11
+ empty? ?
12
+ self :
13
+ self[0].chr.capitalize + self[1, size]
14
+ end
15
+
16
+ def cp_case(s)
17
+ send((:downcase unless s.dup.downcase!) || (:upcase unless s.dup.upcase!) || (:upcase_first unless s.dup.upcase_first!) || :to_s)
18
+ end
19
+
20
+ def upcase_first!
21
+ self == (result = upcase_first) ? nil : replace(result)
22
+ end
23
+
24
+ def cp_case!(s)
25
+ self == (result = cp_case(s)) ? nil : replace(result)
26
+ end
27
+
28
+ # -- end
29
+
30
+ def singularize!
31
+ downcase == (result = singularize).downcase ? nil : replace(result)
32
+ end
33
+
34
+ def pluralize!
35
+ downcase == (result = pluralize).downcase ? nil : replace(result)
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,82 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module String
6
+ module Internationalization
7
+
8
+ def self.included(base)
9
+ base.send :include, InstanceMethods
10
+ end
11
+
12
+ module InstanceMethods
13
+ def t(options = {})
14
+ self.split(" ").collect do |string|
15
+ key = string.include?(".") ? string.dup : "word.#{string}"
16
+ default = key.split(".").last
17
+ translating_word = key.starts_with?("word.")
18
+
19
+ key.downcase!
20
+ options[:pluralize] = "".respond_to?(:pl) && (options[:pluralize].nil? || options[:pluralize])
21
+ options[:translate_callback] ||= LOGGER_PROC if RAILS_ENV == "development"
22
+
23
+ if options.include? :default
24
+ options[:default] = [options[:default]].flatten << default.humanize
25
+ s = i18n_t key, options
26
+ s = s[:_base] if s.is_a?(Hash)
27
+ value = s.dup
28
+ else
29
+ s = i18n_t key, options.merge({:default => translating_word ? "" : default.humanize})
30
+ value = s.dup
31
+
32
+ if translating_word
33
+ unless (translated = !s.empty?) or !"".respond_to?(:pl)
34
+ key.singularize!
35
+ s = i18n_t key, options.merge({:default => ""})
36
+ value = s.dup
37
+ end
38
+
39
+ if s.empty?
40
+ s = default.humanize
41
+ value = s.dup
42
+ else
43
+ s = s.pl(options[:count]) unless !options[:pluralize] or (options[:count].nil? and default.dup.pluralize!)
44
+ end
45
+ end
46
+ end
47
+
48
+ unless s.gsub!(/^=\s+/, "")
49
+ s.cp_case! options[:capitalize] ? default.capitalize : default
50
+ end
51
+
52
+ EnrichedString.new s, {:key => string, :actual_key => key, :actual_value => value}
53
+
54
+ end.join(" ")
55
+ end
56
+
57
+ private
58
+
59
+ RICH_I18N_OPTIONS = [:count, :pluralize, :capitalize, :translate_callback]
60
+ LOGGER_PROC = Proc.new{|translation, key, options| puts "INFO: I18n.t #{key.inspect}, #{options.inspect}"}
61
+
62
+ @@i18n_translations = {}
63
+
64
+ def i18n_t(key, opts = {})
65
+ options = opts.inject({}) do |hash, (k, v)|
66
+ hash[k] = v.is_a?(String) && v.include?("<i18n") ? v.gsub(/(\<i18n[^\>]+\>)|(\<\/i18n\>)/, "") : v unless RICH_I18N_OPTIONS.include?(k)
67
+ hash
68
+ end
69
+
70
+ k = "#{key.inspect}, #{options.inspect}"
71
+ translation = (@@i18n_translations[k] ||= I18n.t(key, options).dup)
72
+ opts[:translate_callback].try :call, translation, key, options
73
+
74
+ translation
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "rich/i18n/core/symbol/internationalization"
3
+
4
+ class Symbol
5
+ include Rich::I18n::Core::Symbol::Internationalization
6
+ end
@@ -0,0 +1,16 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Core
5
+ module Symbol
6
+ module Internationalization
7
+
8
+ def t(options = {})
9
+ to_s.t options
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Engine
5
+ extend self
6
+
7
+ attr_accessor :enable_enriched_output
8
+
9
+ def init(test_class = nil)
10
+ if test_class
11
+ test_locale = test_class.name.match(/(Rich\:\:I18n\:\:Test\:\:Locales\:\:)(\w+)/).captures[1].downcase.to_sym
12
+
13
+ I18n.load_path = [File.join(File.dirname(__FILE__), "..", "..", "..", "locales", "#{test_locale}.yml")]
14
+ else
15
+ I18n.load_path += Dir[File.join(File.dirname(__FILE__), "..", "..", "..", "locales", "*.yml")]
16
+ end
17
+
18
+ I18n.backend.reload!
19
+
20
+ test_locale
21
+ end
22
+
23
+ def can_enrich_output?
24
+ !enable_enriched_output.blank? and (enable_enriched_output.is_a?(Symbol) ? (send(enable_enriched_output) rescue false) : enable_enriched_output)
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+
31
+ Rich::I18n::Engine.init
@@ -0,0 +1,51 @@
1
+
2
+ module Rich
3
+ module I18n
4
+ module Formtastic
5
+
6
+ def self.included(base)
7
+ base.alias_method_chain :input, :enrichments
8
+ end
9
+
10
+ def input_with_enrichments(*args)
11
+ object = (@object.class.name if @object) || @object_name.match(/\[(\w+)_attributes\]/).captures.first.classify
12
+ method_arg = args.shift
13
+ method = method_arg.to_s
14
+ options = args.extract_options!
15
+ wrapper_tag = options.delete(:wrapper_tag)
16
+
17
+ unless options.include?(:label)
18
+ keys = [:"label.#{object}.#{method}", :"label.#{method}", :"word.#{method}"]
19
+
20
+ if @options.include?(:name)
21
+ keys.unshift :"label.forms.(#{@options[:name]}).#{method}"
22
+ keys.unshift :"label.forms.(#{@options[:name]}).#{object}.#{method}"
23
+ end
24
+
25
+ options[:label] = keys.shift.t(:default => keys, :capitalize => true).to_output
26
+ end
27
+
28
+ unless options.include?(:seatholder)
29
+ keys = [:"seatholder.#{object}.#{method}", :"seatholder.#{method}", ""]
30
+
31
+ if @options.include?(:name)
32
+ keys.unshift :"seatholder.forms.(#{@options[:name]}).#{method}"
33
+ keys.unshift :"seatholder.forms.(#{@options[:name]}).#{object}.#{method}"
34
+ end
35
+
36
+ seatholder = keys.shift.t :default => keys, :capitalize => true
37
+ options[:seatholder] = seatholder.to_output unless seatholder.empty?
38
+ end
39
+
40
+ (options[:input_html] ||= {}).store :seatholder, options.delete(:seatholder) unless @object && @object.respond_to?(:errors) && !@object.errors[method.to_sym].blank?
41
+
42
+ if (output = input_without_enrichments method_arg, options) and wrapper_tag
43
+ output.gsub(/^\<li/, "<#{wrapper_tag}").gsub(/\<\/li\>$/, "</#{wrapper_tag}>")
44
+ else
45
+ output
46
+ end
47
+ end
48
+
49
+ end
50
+ end
51
+ end