jerome-localized-frontend 0.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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 August Lilleaas
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,54 @@
1
+ = Localized Frontend
2
+
3
+ http://gitorious.org/projects/localized-frontend/
4
+ http://github.com/leethal/localized-frontend/
5
+
6
+ Localizing the front-end of single language Rails apps.
7
+
8
+ The localizations are stored in YAML files. Create a spanish.yml file, call
9
+ LocalizedFrontend.in :spanish somewhere in your app (probably in environment.rb or an
10
+ initializer), and rejoice!
11
+
12
+ It localizes inflectors (pluralize, singularize etc), Active Record error messages, month
13
+ and day names, form labels (<%= f.label :foo %>) and Array#to_sentence.
14
+
15
+ == To contributors
16
+
17
+ Feel free to submit your own translations and localizations! You can mail me patches on
18
+ augustlilleaas@gmail.com, or you can fork the Git repository on
19
+ http://github.com/leethal/localized-frontend/ and send a pull request. Or write it down on
20
+ paper and mail it to me. Your call!
21
+
22
+ Keep in mind that the YAML file is whiny - certain keys and values are required in
23
+ order to avoid errors being raised. At the moment, the tests are hardcoded in Norwegian.
24
+ That should probably change, so that one can set the language in an environment
25
+ variable and run the tests in whatever language one might prefer.
26
+
27
+ Also, the code is fairly hard to grok, as it's mostly monkey patches. Feel free to improve
28
+ the readability of the code!
29
+
30
+ == What it does
31
+
32
+ Here's a short list of features (examples are in norwegian)
33
+
34
+ Localizing %b, %B, %a and %A in Time#strftime, Date#strftime and DateTime#strftime
35
+
36
+ * Time.now.strftime('%b') => okt
37
+ * Time.now.strftime('%b') => oktober
38
+ * Time.now.strftime('%a') => søn
39
+ * Time.now.strftime('%A') => søndag
40
+
41
+ Localized inflections. "bil".pluralize => "biler"
42
+
43
+ Localizing attribute names in ActiveRecord.
44
+
45
+ class Question < ActiveRecord::Base
46
+ localized_fields :question => "Spørsmål", :answer => "Svar"
47
+ end
48
+
49
+ == TODO
50
+
51
+ * Make tests runnable in any language. In other words, don't let tests be hardcoded in Norwegian.
52
+
53
+
54
+ Copyright (c) 2008 August Lilleaas, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the translated plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the translated plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Translated'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ * Look for deprecation errors and kill them on sight!
2
+ * http://github.com/rails/rails/commit/4f75840d72b96fff34d65b59480da7d6c7494120
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'localized_frontend'
@@ -0,0 +1,15 @@
1
+ require 'localized_frontend/core'
2
+ require 'localized_frontend/inflector_extension'
3
+ require 'localized_frontend/active_record_extension'
4
+ require 'localized_frontend/strftime'
5
+ require 'localized_frontend/to_sentence'
6
+ require 'localized_frontend/form_labels'
7
+ require 'localized_frontend/date_helper'
8
+
9
+ module LocalizedFrontend
10
+ # Raised when a localization method is called but the language isn't set. Set it with
11
+ # <tt>LocalizedFrontend.in</tt>.
12
+ class LanguageNotSet < StandardError; end
13
+
14
+ include Core
15
+ end
@@ -0,0 +1,13 @@
1
+ %w(translatable_column_names error_messages).each do |extension|
2
+ require File.join(File.dirname(__FILE__), 'active_record_extension', extension)
3
+ end
4
+
5
+ module LocalizedFrontend
6
+ # Active Record extensions. Refer to child modules for the rock 'n roll.
7
+ module ActiveRecordExtension
8
+ def self.included(base)
9
+ include TranslatableColumnNames
10
+ include ErrorMessages
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module LocalizedFrontend
2
+ module ActiveRecordExtension
3
+ # Hooks into Active Record's validations so that error messages returns a localized version of
4
+ # the column names, if defined. See TranslatableColumnNames for information on how to define
5
+ # these localizations.
6
+ module ErrorMessages
7
+ def self.included(base)
8
+ replace_default_error_messages
9
+ hook_human_attribute_name
10
+ end
11
+
12
+ # Merge the localized definitions into Active Record's definitions.
13
+ def self.replace_default_error_messages
14
+ ActiveRecord::Errors.default_error_messages.merge!(LocalizedFrontend['validation_error_messages'].symbolize_keys)
15
+ end
16
+
17
+ # human_attribute_name is what Active Record calls when looking for the attribute name on
18
+ # error messages. This method injects a localization attempt that fallbacks on the default
19
+ # column name representation if no localization was found.
20
+ def self.hook_human_attribute_name
21
+ ActiveRecord::Base.class_eval do
22
+ def self.human_attribute_name(attribute)
23
+ localized_fields[attribute] || attribute.humanize
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ module LocalizedFrontend
2
+ module ActiveRecordExtension
3
+ # Makes localized attribute names defineable in models. Example:
4
+ #
5
+ # class Post < ActiveRecord::Base
6
+ # localized_fields :title => 'Smuuk smiik smakeke'
7
+ # end
8
+ module TranslatableColumnNames
9
+ def self.included(base)
10
+ ActiveRecord::Base.class_inheritable_accessor :localized_attributes
11
+ ActiveRecord::Base.extend ClassMethods
12
+ end
13
+
14
+ module ClassMethods
15
+ # Stores a set of localized attributes in a hash, so that these localized variants can be
16
+ # used to localize validation error messages.
17
+ #
18
+ # class Post < ActiveRecord::Base
19
+ # localized_fields :title => 'Smuuk smiik smakeke'
20
+ # validates_presence_of :title
21
+ # end
22
+ #
23
+ # p = Post.new
24
+ # p.valid?
25
+ # p.errors.full_messages # => ['Smuuk smiik smakeke is required']
26
+ # # (fyi, the 'is required' part can also be localized)
27
+ def localized_fields(options = {})
28
+ self.localized_attributes ||= HashWithIndifferentAccess.new
29
+ self.localized_attributes.merge!(options)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,62 @@
1
+ module LocalizedFrontend
2
+ # The main module that adds class methods to LocalizedFrontend and creates the hooks we need. See
3
+ # the individual methods for more information.
4
+ module Core
5
+ # Creates the LocalizedFrontend.language accessor and stuff.
6
+ def self.included(base)
7
+ base.mattr_accessor :language
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ # Sets the current language.
13
+ #
14
+ # LocalizedFrontend.in :french
15
+ def in(language)
16
+ self.language = language
17
+ first_time_inclusion
18
+ change_language!
19
+ end
20
+
21
+ # Returns the current language as a hash, or raises LanguageNotSet if (woha) the language isn't set.
22
+ def current_language(reload = false)
23
+ begin
24
+ @current_language = nil if reload
25
+ @current_language ||= YAML::load_file(File.join(File.dirname(__FILE__), "..", "translations", "#{language}.yml"))
26
+ rescue Errno::ENOENT
27
+ raise LocalizedFrontend::LanguageNotSet
28
+ end
29
+ end
30
+
31
+ # A shortcut to current language. These are equivalents:
32
+ #
33
+ # LocalizedFrontend.current_language['foos']
34
+ # LocalizedFrontend['foos']
35
+ def [](key)
36
+ current_language[key]
37
+ end
38
+
39
+ private
40
+
41
+ # Dirty. Fix, please.
42
+ def first_time_inclusion
43
+ return if @included
44
+
45
+ LocalizedFrontend.class_eval do
46
+ include InflectorExtension
47
+ include ActiveRecordExtension
48
+ include Strftime
49
+ include ToSentence
50
+ include FormLabels
51
+ end
52
+
53
+ @included = true
54
+ end
55
+
56
+ def change_language!
57
+ # Reload the current language hash.
58
+ current_language(true)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,36 @@
1
+ module LocalizedFrontend
2
+ module DateHelper
3
+ def self.included(base)
4
+ ActionView::Helpers::DateHelper.class_eval do
5
+ def select_month_with_localization(date, options = {}, html_options = {})
6
+ val = date ? (date.kind_of?(Fixnum) ? date : date.month) : ''
7
+ if options[:use_hidden]
8
+ hidden_html(options[:field_name] || 'month', val, options)
9
+ else
10
+ month_options = []
11
+ month_names = options[:use_month_names] || (options[:use_short_month] ? LocalizedFrontend['month_names']['abbreviated']: LocalizedFrontend['month_names']['full'])
12
+ month_names.unshift(nil) if month_names.size < 13
13
+ 1.upto(12) do |month_number|
14
+ month_name = if options[:use_month_numbers]
15
+ month_number
16
+ elsif options[:add_month_numbers]
17
+ month_number.to_s + ' - ' + month_names[month_number]
18
+ else
19
+ month_names[month_number]
20
+ end
21
+
22
+ month_options << ((val == month_number) ?
23
+ content_tag(:option, month_name, :value => month_number, :selected => "selected") :
24
+ content_tag(:option, month_name, :value => month_number)
25
+ )
26
+ month_options << "\n"
27
+ end
28
+ select_html(options[:field_name] || 'month', month_options.join, options, html_options)
29
+ end
30
+ end
31
+ end
32
+
33
+ ActionView::Helpers::DateHelper.alias_method_chain :select_month, :localization
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ module LocalizedFrontend
2
+ # The default form builders label method tries to find a localized definition
3
+ # of the attribute.
4
+ #
5
+ # <%= f.label :title %> (returns 'Localized Version of Title That Is Defined In the Model')
6
+ module FormLabels
7
+ def self.included(base)
8
+ ActionView::Helpers::FormBuilder.class_eval do
9
+ def label_with_localization(method, text = nil, options = {})
10
+ if @object
11
+ text ||= @object.class.localized_attributes ? @object.class.localized_attributes[method] : nil
12
+ end
13
+ label_without_localization(method, text, options)
14
+ end
15
+ end
16
+
17
+ ActionView::Helpers::FormBuilder.alias_method_chain :label, :localization
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,131 @@
1
+ module LocalizedFrontend
2
+ # Handles localization of inflections (pluralize, singularize etc.)
3
+ module InflectorExtension
4
+ def self.included(base)
5
+ add_localized_pluralizations_to_string
6
+ extend_inflector_class
7
+ initialize_localized_rules
8
+ set_localized_inflections
9
+ end
10
+
11
+ # Adds the local_puralize and local_singularize methods to String. These methods are
12
+ # used to get a localized pluralization/singularization.
13
+ #
14
+ # LocalizedFrontend.in :norwegian
15
+ # "car".pluralize # => "cars"
16
+ # "car".local_pluralize # => "carer"
17
+ # "bil".local_pluralize # => "biler"
18
+ def self.add_localized_pluralizations_to_string
19
+ String.class_eval { include StringInstanceMethods }
20
+ end
21
+
22
+ # Hooks into the inflector instance and adds the methods we need in order to get
23
+ # localized inflections. The real meat is the in_localized_scope method.
24
+ def self.extend_inflector_class
25
+ Inflector.inflections.class.class_eval { attr_accessor :localize }
26
+ Inflector.inflections.instance_eval { extend InflectorInstanceMethods }
27
+ end
28
+
29
+ # We store the localized inflections in a separate set of instance variables. See
30
+ # InflectorInstanceMethods
31
+ def self.initialize_localized_rules
32
+ Inflector.inflections.instance_eval do
33
+ @localized_plurals, @localized_singulars, @localized_uncountables = [], [], []
34
+ end
35
+ end
36
+
37
+ # The real meat that loops through the defined inflections and hooks them into the
38
+ # monkey patched Inflector.
39
+ def self.set_localized_inflections
40
+ Inflector.inflections.plurals
41
+ Inflector.inflections.in_localized_scope do
42
+ Inflector.inflections.current_scope('plurals')
43
+ end
44
+ Inflector.inflections.in_localized_scope do
45
+ %w(singular plural irregular).each do |type|
46
+ next unless LocalizedFrontend['inflections'][type]
47
+
48
+ LocalizedFrontend['inflections'][type].each do |rule, replacement|
49
+ Inflector.inflections.send(type, case_insensitive_regular_expression(rule), replacement)
50
+ end
51
+ end
52
+
53
+ Inflector.inflections.uncountable(LocalizedFrontend['inflections']['uncountable'])
54
+ end
55
+ end
56
+
57
+ # That's what the 'true' means. Case insensitive.
58
+ def self.case_insensitive_regular_expression(rule)
59
+ Regexp.new(rule, true)
60
+ end
61
+
62
+ # The in_localized_scope method is the only thing you need here. Everything else is obscure
63
+ # and retarded.
64
+ #
65
+ # The methods +plural+, +singular+ and +uncountable+ is a simple re-definition of the original
66
+ # method in Inflector. The change is simple - use methods instead of instance variables. So, when
67
+ # the +plural+ method used to do @plurals.insert, we change it so that it does plurals.insert. Then,
68
+ # these methods (+singulars+, +plurals+ and +uncountables+) are returning the inflections we want in
69
+ # the language we request. If +Inflector.inflections.localize+ is set to true, we'll get
70
+ # @localized_plurals. If it's set to false, we get the default @plurals (which the original,
71
+ # un-overrided methods was originally using).
72
+ #
73
+ # +irregulars+ are not re-defined, as that method is calling the +plural+ and +singular+ methods
74
+ # anyway. Which we have already overrided.
75
+ module InflectorInstanceMethods
76
+ # Sets the scope as localized. This is what String#local_pluralize and friends does.
77
+ #
78
+ # "car".pluralize # => "cars"
79
+ # "car".localized_pluralize # => "carer"
80
+ # Inflector.inflections.in_localized_scope { "car".pluralize } # => "carer"
81
+ def in_localized_scope(&block)
82
+ self.localize = true
83
+ result = yield
84
+ self.localize = false
85
+
86
+ result
87
+ end
88
+
89
+ def current_scope(type)
90
+ prefix = localize ? "localized_" : nil
91
+ instance_variable_get("@#{prefix}#{type}")
92
+ end
93
+
94
+ def singulars
95
+ current_scope(:singulars)
96
+ end
97
+
98
+ def plurals
99
+ current_scope(:plurals)
100
+ end
101
+
102
+ def uncountables
103
+ current_scope(:uncountables)
104
+ end
105
+
106
+ def plural(rule, replacement)
107
+ plurals.insert(0, [rule, replacement])
108
+ end
109
+
110
+ def singular(rule, replacement)
111
+ singulars.insert(0, [rule, replacement])
112
+ end
113
+
114
+ def uncountable(*words)
115
+ (uncountables << words).flatten!
116
+ end
117
+ end
118
+
119
+ module StringInstanceMethods
120
+ # A localized version of String#pluralize
121
+ def local_pluralize
122
+ Inflector.inflections.in_localized_scope { pluralize }
123
+ end
124
+
125
+ # A localized version of String#singularize
126
+ def local_singularize
127
+ Inflector.inflections.in_localized_scope { singularize }
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,36 @@
1
+ module LocalizedFrontend
2
+ # Localizes Time#strftime, Date#strftime and DateTime#strftime.
3
+ module Strftime
4
+ # Includes the InstanceMethods module into Time, Date and DateTime.
5
+ def self.included(base)
6
+ [Time, Date, DateTime].each do |klass|
7
+ klass.class_eval { include InstanceMethods }
8
+ end
9
+ end
10
+
11
+ module InstanceMethods
12
+ def self.included(base)
13
+ base.alias_method_chain :strftime, :localization
14
+ end
15
+
16
+ # A rather ugly hack that gsubs the keys we're looking for and replaces it with
17
+ # localized strings, and then passes the format string to the original strftime
18
+ # method. "%Y %B" turns into, say, "%Y Juni", and is passed to strftime.
19
+ #
20
+ # Time/Date/DateTime#strftime_without_localization can be called in order to
21
+ # bypass this.
22
+ def strftime_with_localization(format = '%F')
23
+ _weekday = self.wday - 1
24
+ _month = self.month - 1
25
+
26
+ format.gsub!(/%a/, LocalizedFrontend['day_names']['abbreviated'][_weekday])
27
+ format.gsub!(/%A/, LocalizedFrontend['day_names']['full'][_weekday])
28
+
29
+ format.gsub!(/%b/, LocalizedFrontend['month_names']['abbreviated'][_month])
30
+ format.gsub!(/%B/, LocalizedFrontend['month_names']['full'][_month])
31
+
32
+ strftime_without_localization(format)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ module LocalizedFrontend
2
+ # Localizes the connector and the skip_last_comma settings for Array#to_sentence
3
+ module ToSentence
4
+ def self.included(base)
5
+ Array.class_eval { include InstanceMethods }
6
+ end
7
+
8
+ module InstanceMethods
9
+ def self.included(base)
10
+ base.alias_method_chain :to_sentence, :localization
11
+ end
12
+
13
+ def to_sentence_with_localization(options = {})
14
+ options.reverse_merge! :connector => LocalizedFrontend['to_sentence']['connector'], :skip_last_comma => LocalizedFrontend['to_sentence']['skip_last_comma']
15
+ to_sentence_without_localization(options)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,59 @@
1
+ day_names:
2
+ abbreviated:
3
+ - Dim
4
+ - Lun
5
+ - Mar
6
+ - Mer
7
+ - Jeu
8
+ - Ven
9
+ - Sam
10
+ full:
11
+ - Dimanche
12
+ - Lundi
13
+ - Mardi
14
+ - Mercredi
15
+ - Jeudi
16
+ - Vendredi
17
+ - Samedi
18
+
19
+ month_names:
20
+ abbreviated:
21
+ - jan
22
+ - fév
23
+ - mar
24
+ - avr
25
+ - mai
26
+ - jun
27
+ - jul
28
+ - aou
29
+ - sep
30
+ - oct
31
+ - nov
32
+ - dec
33
+ full:
34
+ - janvier
35
+ - février
36
+ - mars
37
+ - avril
38
+ - mai
39
+ - juin
40
+ - juillet
41
+ - août
42
+ - septembre
43
+ - octobre
44
+ - novembre
45
+ - décembre
46
+
47
+ inflections:
48
+ plural:
49
+ '$': 's'
50
+ singular:
51
+ 's$': ''
52
+ uncountable:
53
+
54
+ to_sentence:
55
+ connector: et
56
+ skip_last_comma: true
57
+
58
+ validation_error_messages:
59
+ inclusion: n'est pas dans la liste
@@ -0,0 +1,79 @@
1
+ day_names:
2
+ abbreviated:
3
+ - Søn
4
+ - Man
5
+ - Tir
6
+ - Ons
7
+ - Tor
8
+ - Fre
9
+ - Lør
10
+ full:
11
+ - Søndag
12
+ - Mandag
13
+ - Tirsdag
14
+ - Onsdag
15
+ - Torsdag
16
+ - Fredag
17
+ - Lørdag
18
+
19
+ month_names:
20
+ abbreviated:
21
+ - Jan
22
+ - Feb
23
+ - Mar
24
+ - Apr
25
+ - Mai
26
+ - Jun
27
+ - Jul
28
+ - Aug
29
+ - Sep
30
+ - Okt
31
+ - Nov
32
+ - Des
33
+ full:
34
+ - Januar
35
+ - Februar
36
+ - Mars
37
+ - April
38
+ - Mai
39
+ - Juni
40
+ - Juli
41
+ - August
42
+ - September
43
+ - Oktober
44
+ - November
45
+ - Desember
46
+
47
+ inflections:
48
+ plural:
49
+ '$': 'er'
50
+ singular:
51
+ 'er$': ''
52
+ uncountable:
53
+ - hus
54
+ - tak
55
+
56
+ to_sentence:
57
+ connector: og
58
+ skip_last_comma: true
59
+
60
+ validation_error_messages:
61
+ inclusion: er ikke i lista
62
+ exclusion: er reservert
63
+ invalid: er ugyldig
64
+ confirmation: stemmer ikke overens
65
+ accepted: må aksepteres
66
+ empty: må fylles ut
67
+ blank: må fylles ut
68
+ too_long: er for lang (maks %d tegn)
69
+ too_short: er for kort (minst %d tegn)
70
+ wrong_length: har feil lengde (skal være %d tegn)
71
+ taken: er allerede tatt
72
+ not_a_number: må være et tall
73
+ greater_than: må være høyere enn %d
74
+ greater_than_or_equal_to: må være høyere enn eller lik %d
75
+ equal_to: må være %d
76
+ less_than: må være mindre enn %d
77
+ less_than_or_equal_to: må være mindre enn eller lik %d
78
+ odd: må være et oddetall
79
+ even: må være et partall
@@ -0,0 +1,25 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ActiveRecordExtensionTest < Test::Unit::TestCase
4
+ def test_table_name_pluralization
5
+ assert_equal 'posts', Post.table_name
6
+ end
7
+
8
+ def test_setting_localized_fields
9
+ assert_equal 'Tittel', Post.localized_fields[:title]
10
+ assert_equal 'Tittel', Post.localized_fields['title']
11
+ end
12
+
13
+ def test_overriding_default_error_messages
14
+ assert_equal ActiveRecord::Errors.default_error_messages[:too_short], LocalizedFrontend['validation_error_messages']['too_short']
15
+ end
16
+
17
+ def test_actual_error_message_output
18
+ message = ActiveRecord::Errors.default_error_messages[:blank]
19
+ p = Post.new
20
+ p.valid?
21
+
22
+ assert_equal message, p.errors.on(:title)
23
+ assert p.errors.full_messages.include?("Tittel #{message}")
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ require File.join(File.dirname(__FILE__), "test_helper")
2
+
3
+ class EverythingElseTest < Test::Unit::TestCase
4
+ def test_to_sentence
5
+ assert_equal 'Per, Pål og Espen Askeladd', ['Per', 'Pål', 'Espen Askeladd'].to_sentence
6
+ assert_equal 'Du, jeg, eller meg', ['Du', 'jeg', 'meg'].to_sentence(:connector => 'eller', :skip_last_comma => false)
7
+ end
8
+
9
+ def test_to_sentence_again
10
+ assert_equal 'Per, Pål og Espen Askeladd', ['Per', 'Pål', 'Espen Askeladd'].to_sentence
11
+ assert_equal 'Du, jeg, eller meg', ['Du', 'jeg', 'meg'].to_sentence(:connector => 'eller', :skip_last_comma => false)
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ require File.join(File.dirname(__FILE__), "test_helper")
2
+
3
+ class TranslatedTest < Test::Unit::TestCase
4
+ def setup
5
+ LocalizedFrontend.in :norwegian
6
+
7
+ @controller = DummyController.new
8
+ @request = @controller.request
9
+
10
+ @view = ActionView::Base.new
11
+ @view.assigns['controller'] = @controller
12
+ @view.assigns['_request'] = @request
13
+ @view.assigns['_params'] = @request.params
14
+ end
15
+
16
+ def test_localized_label
17
+ render '<% form_for(Post.new) do |f| %><%= f.label :excerpt %><%= f.label :cheese %><% end %>'
18
+ assert @output =~ Regexp.new('<label for="post_excerpt">Ingress</label>')
19
+ #raise @output.inspect
20
+ end
21
+
22
+ def test_original_label
23
+ render '<% form_for(Post.new) do |f| %><%= f.label :excerpt %><%= f.label :cheese %><% end %>'
24
+ assert @output =~ Regexp.new('<label for="post_cheese">Cheese</label>')
25
+ end
26
+
27
+ def test_unlocalized_model
28
+ render '<% form_for(UnlocalizedFoo.new) do |f| %><%= f.label :foo %><% end %>'
29
+ assert @output =~ Regexp.new('<label for="unlocalized_foo_foo">Foo</label>')
30
+ end
31
+
32
+ def test_symbol
33
+ render '<% form_for(:foo) do |f| %><%= f.label :bar %><% end %>'
34
+ end
35
+
36
+ private
37
+
38
+ def render(template)
39
+ @output = @view.render_template(ActionView::InlineTemplate.new(@view, template))
40
+ end
41
+ end
@@ -0,0 +1,38 @@
1
+ require File.join(File.dirname(__FILE__), "test_helper")
2
+
3
+ class InflectorTest < Test::Unit::TestCase
4
+ def test_original_english_inflections
5
+ assert_equal 'posts', 'post'.pluralize
6
+ assert_equal 'post', 'posts'.singularize
7
+ end
8
+
9
+ def test_singularize
10
+ {"biler" => "bil", "katter" => "katt"}.each do |plural, singular|
11
+ assert_equal singular, plural.local_singularize
12
+ end
13
+ end
14
+
15
+ def test_pluralize
16
+ {"bil" => "biler", "katt" => "katter"}.each do |singular, plural|
17
+ assert_equal plural, singular.local_pluralize
18
+ end
19
+ end
20
+
21
+ def test_irregular
22
+
23
+ end
24
+
25
+ def test_pluralize_uncountable
26
+ %w(hus tak).each do |uncountable|
27
+ assert_equal uncountable, uncountable.local_pluralize
28
+ end
29
+ end
30
+
31
+ def test_adding_inflections
32
+
33
+ end
34
+
35
+ def test_case_insensivity
36
+ assert_equal "BIL", "BILER".local_singularize
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), "test_helper")
2
+
3
+ class StrftimeTest < Test::Unit::TestCase
4
+ def test_localized_strftime_on_time
5
+ assert_localized_strftime Time.now
6
+ end
7
+
8
+ def test_localized_strftime_on_date
9
+ assert_localized_strftime Date.today
10
+ end
11
+
12
+ def test_localized_stfrtime_on_datetime
13
+ assert_localized_strftime DateTime.class_eval { today }
14
+ end
15
+
16
+ def test_localized_stfrtime_on_april_fools_day
17
+ assert_equal Time.utc(2008,4,1).strftime("%B"), "April"
18
+ end
19
+
20
+ private
21
+
22
+ def assert_localized_strftime(time)
23
+ assert_equal LocalizedFrontend['month_names']['abbreviated'][time.month-1], time.strftime("%b")
24
+ assert_equal LocalizedFrontend['month_names']['full'][time.month-1], time.strftime("%B")
25
+
26
+ assert_equal LocalizedFrontend['day_names']['abbreviated'][time.wday-1], time.strftime("%a")
27
+ assert_equal LocalizedFrontend['day_names']['full'][time.wday-1], time.strftime("%A")
28
+ end
29
+ end
@@ -0,0 +1,77 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'active_support'
4
+ require 'active_record'
5
+ require 'action_controller'
6
+ require 'action_controller/test_process'
7
+
8
+ require File.join(File.dirname(__FILE__), "..", "lib", "localized_frontend")
9
+ LocalizedFrontend.in :norwegian
10
+
11
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
12
+ ActiveRecord::Schema.define(:version => 1) do
13
+ create_table :posts do |t|
14
+ t.string :title, :cheese
15
+ t.text :excerpt, :body
16
+ end
17
+
18
+ create_table(:unlocalized_foos) {|t| t.string :foo }
19
+ end
20
+
21
+ class Post < ActiveRecord::Base
22
+ localized_fields :title => "Tittel", :excerpt => "Ingress", :body => "Brødtekst"
23
+
24
+ validates_presence_of :title, :excerpt, :body
25
+ end
26
+
27
+ class UnlocalizedFoo < ActiveRecord::Base
28
+ end
29
+
30
+ # The following is ninjaed from will_paginate.
31
+ ActionController::Routing::Routes.draw do |map|
32
+ map.resources :posts, :unlocalized_foos
33
+ map.connect ':controller/:action/:id'
34
+ end
35
+ ActionController::Base.perform_caching = false
36
+
37
+ class ActionView::Base
38
+ def protect_against_forgery?
39
+ false
40
+ end
41
+ end
42
+ class DummyRequest
43
+ attr_accessor :symbolized_path_parameters
44
+
45
+ def initialize
46
+ @get = true
47
+ @params = {}
48
+ @symbolized_path_parameters = { :controller => 'foo', :action => 'bar' }
49
+ end
50
+
51
+ def relative_url_root
52
+ ''
53
+ end
54
+
55
+ def params(more = nil)
56
+ @params.update(more) if more
57
+ @params
58
+ end
59
+ end
60
+
61
+ class DummyController
62
+ attr_reader :request
63
+ attr_accessor :controller_name
64
+
65
+ def initialize
66
+ @request = DummyRequest.new
67
+ @url = ActionController::UrlRewriter.new(@request, @request.params)
68
+ end
69
+
70
+ def params
71
+ @request.params
72
+ end
73
+
74
+ def url_for(params)
75
+ @url.rewrite(params)
76
+ end
77
+ end
@@ -0,0 +1,28 @@
1
+ require File.join(File.dirname(__FILE__), "test_helper")
2
+
3
+ class TranslatedTest < Test::Unit::TestCase
4
+ def test_setting_language
5
+ LocalizedFrontend.in :norwegian
6
+ assert_equal :norwegian, LocalizedFrontend.language
7
+ end
8
+
9
+ def test_fails_with_no_language_set
10
+ LocalizedFrontend.language = nil
11
+ assert_raises(LocalizedFrontend::LanguageNotSet) { LocalizedFrontend.current_language(true) }
12
+ assert_raises(LocalizedFrontend::LanguageNotSet) { LocalizedFrontend['month_names'] }
13
+ end
14
+
15
+ def test_current_language
16
+ assert LocalizedFrontend.current_language.is_a?(Hash)
17
+ end
18
+
19
+ def test_accessing_with_brackets
20
+ assert_equal LocalizedFrontend['month_names'], LocalizedFrontend.current_language['month_names']
21
+ end
22
+
23
+ def test_changing_language
24
+ norwegian = LocalizedFrontend.current_language.dup
25
+ LocalizedFrontend.in :french
26
+ assert_not_equal norwegian, LocalizedFrontend.current_language
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jerome-localized-frontend
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - August Lilleaas
8
+ - "J\xC3\xA9r\xC3\xB4me Lipowicz"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2008-10-10 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description:
18
+ email: augustlilleaas@gmail.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - init.rb
27
+ - MIT-LICENSE
28
+ - Rakefile
29
+ - README
30
+ - TODO
31
+ - lib/localized_frontend.rb
32
+ - lib/localized_frontend/active_record_extension.rb
33
+ - lib/localized_frontend/core.rb
34
+ - lib/localized_frontend/date_helper.rb
35
+ - lib/localized_frontend/form_labels.rb
36
+ - lib/localized_frontend/inflector_extension.rb
37
+ - lib/localized_frontend/strftime.rb
38
+ - lib/localized_frontend/to_sentence.rb
39
+ - lib/translations/french.yml
40
+ - lib/translations/norwegian.yml
41
+ - lib/localized_frontend/active_record_extension/error_messages.rb
42
+ - lib/localized_frontend/active_record_extension/translatable_column_names.rb
43
+ has_rdoc: false
44
+ homepage: http://github.com/leethal/localized-frontend/
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.2.0
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: Localize the frontend of single language Rails apps.
69
+ test_files:
70
+ - test/active_record_test.rb
71
+ - test/everything_else_test.rb
72
+ - test/form_labels_test.rb
73
+ - test/inflector_test.rb
74
+ - test/strftime_test.rb
75
+ - test/test_helper.rb
76
+ - test/translated_test.rb