locale_selector 1.93.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +81 -0
- data/Rakefile +40 -0
- data/TESTING.rdoc +8 -0
- data/generators/gettext_hacks/gettext_hacks_generator.rb +15 -0
- data/generators/gettext_hacks/templates/gettext_hacks.rb +40 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/locale_selector/gettext_tasks.rb +170 -0
- data/lib/locale_selector.rb +266 -0
- data/locale_selector.gemspec +21 -0
- data/rails/init.rb +1 -0
- data/uninstall.rb +1 -0
- metadata +83 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 [name of plugin creator]
|
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.rdoc
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
= locale_selector
|
2
|
+
|
3
|
+
locale_selector provides a wrapper around the excellent ruby-gettext gem
|
4
|
+
http://www.yotabanana.com/hiki/ruby-gettext.html
|
5
|
+
|
6
|
+
Offers a convinient way to specify the list of locales supported by your
|
7
|
+
application. Provides a html UI control for locale selection.
|
8
|
+
Maintains the user preference in a cookie and provides callback for
|
9
|
+
saving the preference e.g. in a database.
|
10
|
+
|
11
|
+
Tested with Rails 2.1 and gettext 1.93.
|
12
|
+
|
13
|
+
locale_selector home page (rdoc): http://locale-selector.rubyforge.org/index.html
|
14
|
+
|
15
|
+
locale_selector rubyforge page (releases etc.): http://rubyforge.org/projects/locale-selector
|
16
|
+
|
17
|
+
source repository on github: http://github.com/geekq/locale_selector
|
18
|
+
|
19
|
+
= Installation
|
20
|
+
|
21
|
+
1.Install as a gem with
|
22
|
+
|
23
|
+
gem install locale_selector
|
24
|
+
|
25
|
+
It also installs the required gettext gem.
|
26
|
+
|
27
|
+
2.Append following to the Rakefile of your Rails application to get the
|
28
|
+
gettext related tasks
|
29
|
+
|
30
|
+
require 'locale_selector/gettext_tasks'
|
31
|
+
|
32
|
+
`rake -T gettext` now offers a couple of new tasks.
|
33
|
+
|
34
|
+
3.Reference the gettext in your environment.rb. For Rails 2.1 put following
|
35
|
+
at the top of Rails::Initializer.run block:
|
36
|
+
|
37
|
+
config.gem 'gettext', :lib => 'gettext/rails', :version => '1.93'
|
38
|
+
config.gem 'locale_selector', :version => '1.93'
|
39
|
+
|
40
|
+
4.Run the generator to create an initializer with the gettext hacks
|
41
|
+
|
42
|
+
script/generate gettext_hacks
|
43
|
+
|
44
|
+
5.Please provide the root route in your routes.rb and delete the public/index.html
|
45
|
+
|
46
|
+
map.root :controller => "mycontroller"
|
47
|
+
|
48
|
+
|
49
|
+
= Usage
|
50
|
+
|
51
|
+
Please see +LocaleSelector+ for API documentation and usage examples.
|
52
|
+
|
53
|
+
|
54
|
+
= Versioning
|
55
|
+
|
56
|
+
The version numbers of locale_selector match the version of the gettext gem
|
57
|
+
it is based on.
|
58
|
+
|
59
|
+
= Maintaining translations
|
60
|
+
|
61
|
+
Please use the provided rake tasks for maintaining translations.
|
62
|
+
Run <tt>rake -T gettext</tt> to see the list of provided rake tasks.
|
63
|
+
|
64
|
+
Most frequently used are
|
65
|
+
|
66
|
+
rake gettext:updatepo
|
67
|
+
|
68
|
+
to extract the new strings from the application.
|
69
|
+
Note: please make sure, that all the database connections used
|
70
|
+
in your models work. Gettext connects to the database to extract
|
71
|
+
field names to be translated.
|
72
|
+
|
73
|
+
|
74
|
+
rake gettext:makemo
|
75
|
+
|
76
|
+
for compiling the binary mo files from po-s.
|
77
|
+
|
78
|
+
|
79
|
+
Author:: Vladimir Dobriakov (http://www.innoq.com/blog/vd)
|
80
|
+
Copyright:: Vodafone, 2008
|
81
|
+
License:: MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rake/rdoctask'
|
7
|
+
|
8
|
+
desc 'Default: run unit tests.'
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
desc 'Test the locale_selector plugin.'
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
puts "locale_selector is tested within a simple test apllication."
|
14
|
+
puts "Please run `rake test` in the test/TestApp folder."
|
15
|
+
end
|
16
|
+
|
17
|
+
load File.join(File.dirname(__FILE__), 'locale_selector.gemspec')
|
18
|
+
|
19
|
+
desc 'Generate documentation for the locale_selector plugin.'
|
20
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
21
|
+
rdoc.rdoc_dir = 'rdoc'
|
22
|
+
rdoc.title = 'LocaleSelector'
|
23
|
+
rdoc.options = SPEC.rdoc_options
|
24
|
+
|
25
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
26
|
+
rdoc.rdoc_files.include('generators/gettext_hacks/templates/gettext_hacks.rb')
|
27
|
+
rdoc.rdoc_files.include(SPEC.extra_rdoc_files)
|
28
|
+
end
|
29
|
+
|
30
|
+
Rake::GemPackageTask.new(SPEC) do |p|
|
31
|
+
p.gem_spec = SPEC
|
32
|
+
p.need_tar = true
|
33
|
+
p.need_zip = true
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'Publish the home page'
|
37
|
+
task :publish => :rerdoc do
|
38
|
+
sh 'scp -r rdoc/* geekq@rubyforge.org:/var/www/gforge-projects/locale-selector'
|
39
|
+
end
|
40
|
+
|
data/TESTING.rdoc
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
= Testing
|
2
|
+
|
3
|
+
This plugin does some integration work. It barely makes sense to test it in
|
4
|
+
isolation. It was originally developed as part of a real application and was
|
5
|
+
tested in the context of that application.
|
6
|
+
|
7
|
+
Now where it is published as a plugin, a small test application is the right
|
8
|
+
way to test the plugin.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class GettextHacksGenerator < Rails::Generator::Base
|
2
|
+
|
3
|
+
def initialize(*runtime_args)
|
4
|
+
super(*runtime_args)
|
5
|
+
end
|
6
|
+
|
7
|
+
def manifest
|
8
|
+
record do |m|
|
9
|
+
m.directory File.join('config/initializers')
|
10
|
+
|
11
|
+
m.template 'gettext_hacks.rb', File.join('config/initializers', "gettext_hacks.rb")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module GetText
|
2
|
+
# Modification of the original gettext.
|
3
|
+
#
|
4
|
+
# By default all the translated texts from the po files are also html escaped
|
5
|
+
# so translators can not break the application by introducing less-than
|
6
|
+
# and ampersand characters or by trying to incorporate the <blink> tag ;-)
|
7
|
+
#
|
8
|
+
# It is possible though to turn this feature off for particular messages:
|
9
|
+
# if msgid starts with '#no_html_escaping#' then the translation returned as is,
|
10
|
+
# without html escaping.
|
11
|
+
def gettext(msgid)
|
12
|
+
translated = sgettext(msgid, nil)
|
13
|
+
if msgid =~ /^#no_html_escaping#/
|
14
|
+
translated
|
15
|
+
else
|
16
|
+
esc_html translated
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def esc_html(txt)
|
21
|
+
txt.gsub(/\"|\>|\&|\</) {|ptrn| {'"' => '"', '>' => '>', '<' => '<', '&' => '&'}[ptrn] }
|
22
|
+
end
|
23
|
+
|
24
|
+
alias :_ :gettext
|
25
|
+
module_function :_, :esc_html
|
26
|
+
end
|
27
|
+
|
28
|
+
module ActiveRecord # :nodoc:
|
29
|
+
class Errors
|
30
|
+
# We adjust the gettext so the inclusion of the field name must be done explicitely
|
31
|
+
# with #{fn}. If it is omitted, then the field name is not included.
|
32
|
+
# Originally it was 'append_field = true' so if there was no #{fn} then
|
33
|
+
# the field name was appended at the beginning of the message - very
|
34
|
+
# questionable behaviour.
|
35
|
+
def localize_error_messages_with_better_default(append_field = false)
|
36
|
+
localize_error_messages_without_better_default(append_field)
|
37
|
+
end
|
38
|
+
alias_method_chain :localize_error_messages, :better_default
|
39
|
+
end
|
40
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'locale_selector'
|
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
puts IO.read(File.join(File.dirname(__FILE__), 'README'))
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../locale_selector.rb')
|
2
|
+
require 'gettext'
|
3
|
+
require 'gettext/utils'
|
4
|
+
require 'activesupport'
|
5
|
+
require 'activerecord'
|
6
|
+
|
7
|
+
puts "Loading active_record parsing hacks in gettext_tasks.rb"
|
8
|
+
require 'gettext/rgettext'
|
9
|
+
require 'gettext/parser/active_record'
|
10
|
+
include GetText
|
11
|
+
|
12
|
+
def log(msg)
|
13
|
+
puts msg if false # set verbosity here
|
14
|
+
end
|
15
|
+
|
16
|
+
ActiveRecord::Base.instance_eval do
|
17
|
+
alias inherited_without_log inherited
|
18
|
+
|
19
|
+
@@active_record_classes_list = []
|
20
|
+
|
21
|
+
def inherited(subclass)
|
22
|
+
unless "#{subclass}" =~ /^CGI::/
|
23
|
+
log "registering an ActiveRecord model for later processing: #{subclass}"
|
24
|
+
active_record_classes_list << "#{subclass}"
|
25
|
+
end
|
26
|
+
inherited_without_log(subclass)
|
27
|
+
end
|
28
|
+
|
29
|
+
def active_record_classes_list
|
30
|
+
@@active_record_classes_list
|
31
|
+
end
|
32
|
+
|
33
|
+
def reset_active_record_classes_list
|
34
|
+
@@active_record_classes_list = []
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module GetText
|
39
|
+
module ActiveRecordParser
|
40
|
+
log "overriding the original activerecord parser"
|
41
|
+
|
42
|
+
def self.parse(file, targets = []) # :nodoc:
|
43
|
+
log "locale_selector specific version of activerecordparser.parse is parsing #{file}"
|
44
|
+
GetText.locale = "en"
|
45
|
+
begin
|
46
|
+
eval(open(file).read, TOPLEVEL_BINDING)
|
47
|
+
rescue
|
48
|
+
$stderr.puts _("Ignored '%{file}'. Solve dependencies first.") % {:file => file}
|
49
|
+
$stderr.puts $!
|
50
|
+
end
|
51
|
+
loaded_constants = ActiveRecord::Base.active_record_classes_list
|
52
|
+
ActiveRecord::Base.reset_active_record_classes_list
|
53
|
+
loaded_constants.each do |classname|
|
54
|
+
klass = eval(classname, TOPLEVEL_BINDING)
|
55
|
+
if klass.is_a?(Class) && klass < ActiveRecord::Base
|
56
|
+
log "processing class #{klass.name}"
|
57
|
+
unless (klass.untranslate_all? || klass.abstract_class?)
|
58
|
+
add_target(targets, file, ActiveSupport::Inflector.singularize(klass.table_name.gsub(/_/, " ")))
|
59
|
+
unless klass.class_name == classname
|
60
|
+
add_target(targets, file, ActiveSupport::Inflector.singularize(classname.gsub(/_/, " ").downcase))
|
61
|
+
end
|
62
|
+
begin
|
63
|
+
klass.columns.each do |column|
|
64
|
+
unless untranslate_column?(klass, column.name)
|
65
|
+
if @config[:use_classname]
|
66
|
+
msgid = classname + "|" + klass.human_attribute_name(column.name)
|
67
|
+
else
|
68
|
+
msgid = klass.human_attribute_name(column.name)
|
69
|
+
end
|
70
|
+
add_target(targets, file, msgid)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
rescue
|
74
|
+
$stderr.puts _("No database is available.")
|
75
|
+
$stderr.puts $!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if RubyParser.target?(file)
|
81
|
+
targets = RubyParser.parse(file, targets)
|
82
|
+
end
|
83
|
+
targets.uniq!
|
84
|
+
targets
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def gettext_domain
|
91
|
+
initializer_name = File.join(File.dirname(__FILE__),
|
92
|
+
'../../../../config/initializers/gettext.rb')
|
93
|
+
require initializer_name if File.exist?(initializer_name)
|
94
|
+
|
95
|
+
LocaleSelector::default_domain ||
|
96
|
+
ENV['GETTEXT_DOMAIN'] ||
|
97
|
+
puts("Please either set the LocaleSelector::default_domain in your environment.rb or ENV['GETTEXT_DOMAIN'].") && exit
|
98
|
+
end
|
99
|
+
|
100
|
+
def app_version
|
101
|
+
"#{gettext_domain} 1.0"
|
102
|
+
end
|
103
|
+
|
104
|
+
# based on GetText.update_pofiles
|
105
|
+
def update_po_single_language(textdomain, files, app_version, lang, po_root = "po", refpot = "tmp.pot")
|
106
|
+
rgettext(files, refpot)
|
107
|
+
|
108
|
+
FileUtils.mkdir_p(po_root) unless FileTest.exist? po_root
|
109
|
+
msgmerge("#{po_root}/#{textdomain}.pot", refpot, app_version)
|
110
|
+
|
111
|
+
msgmerge("#{po_root}/#{lang}/#{textdomain}.po", refpot, app_version)
|
112
|
+
|
113
|
+
File.delete(refpot)
|
114
|
+
end
|
115
|
+
|
116
|
+
namespace :gettext do
|
117
|
+
desc "Update pot/po files (text files with translations) " \
|
118
|
+
"Note: please make sure, that all the database connections used " \
|
119
|
+
"in your models work. Gettext connects to the database to extract " \
|
120
|
+
"field names to be translated. " \
|
121
|
+
"Use lang={language to process} or lang=all to process po-files for all languages."
|
122
|
+
task :updatepo => :environment do
|
123
|
+
require 'gettext/utils'
|
124
|
+
puts "Updating translation files for gettext domain #{gettext_domain}"
|
125
|
+
orig_msgmerge = ENV["MSGMERGE_PATH"] || "msgmerge"
|
126
|
+
ENV["MSGMERGE_PATH"] = "#{orig_msgmerge} --no-fuzzy-matching"
|
127
|
+
source_files = Dir.glob(["{app,lib,plugins}/**/*.{rb,erb,rjs,rhtml}", "plugins/**/**/*.{rb,erb,rjs,rhtml}"])
|
128
|
+
lang = ENV['lang']
|
129
|
+
if lang.nil?
|
130
|
+
fail "Use lang={language to process} or lang=all to process po-files for all languages."
|
131
|
+
else
|
132
|
+
# will work in gettext-1.94
|
133
|
+
# options = {:msgmerge => [:no_wrap, :no_fuzzy_matching, :sort_output]}
|
134
|
+
# options[:lang] = lang if lang != 'all'
|
135
|
+
# options[:verbose] = true
|
136
|
+
# puts options.inspect
|
137
|
+
# GetText.update_pofiles(gettext_domain, source_files, app_version, options)
|
138
|
+
|
139
|
+
if lang == 'all'
|
140
|
+
GetText.update_pofiles(gettext_domain, source_files, app_version)
|
141
|
+
else
|
142
|
+
update_po_single_language(gettext_domain, source_files, app_version, lang)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
desc "Compile mo-(machine object) files."
|
148
|
+
task :makemo do
|
149
|
+
require 'gettext/utils'
|
150
|
+
GetText.create_mofiles(true, "po", "locale")
|
151
|
+
end
|
152
|
+
|
153
|
+
desc "Translation for additional (new) language, use lang=xx"
|
154
|
+
task :translate_to do
|
155
|
+
lang = ENV['lang']
|
156
|
+
if lang
|
157
|
+
puts <<-"# # #"
|
158
|
+
Please run:
|
159
|
+
|
160
|
+
mkdir po/#{lang}
|
161
|
+
msginit -i po/#{gettext_domain} -l #{lang} -o po/#{lang}/#{gettext_domain}.po --no-translator
|
162
|
+
svn add po/#{lang}
|
163
|
+
# # #
|
164
|
+
else
|
165
|
+
fail "Please provide the 'lang' parameter on the command line with the desired " +
|
166
|
+
"language code like lang=de"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
require 'uri'
|
2
|
+
=begin rdoc
|
3
|
+
|
4
|
+
= Usage
|
5
|
+
|
6
|
+
== Controller
|
7
|
+
|
8
|
+
In your controllers or in the application controller
|
9
|
+
|
10
|
+
require 'locale_selector'
|
11
|
+
|
12
|
+
and use ControllerClassMethods#offer_locales:
|
13
|
+
|
14
|
+
offer_locales :en_UK, :en_ZA, :de, :ru
|
15
|
+
|
16
|
+
You can use different text domains in different parts of your application,
|
17
|
+
if your application is large enough for multiple translation files.
|
18
|
+
Please provide the differing domain in the single controllers e.g.
|
19
|
+
|
20
|
+
class JobsController < ApplicationController
|
21
|
+
offer_locales :de, :ru, :domain => 'HR_terminology'
|
22
|
+
end
|
23
|
+
|
24
|
+
=== Persisting preferences
|
25
|
+
|
26
|
+
locale_selector provides helpers which you can use in connection with Rails
|
27
|
+
hooks like this:
|
28
|
+
|
29
|
+
class ApplicationController
|
30
|
+
before_filter :persist_locale_choice_cookie
|
31
|
+
after_filter :persist_locale_choice_in_db
|
32
|
+
|
33
|
+
def persist_locale_choice_cookie
|
34
|
+
compute_effective_locale do |requested_locale|
|
35
|
+
save_cookie requested_locale
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def persist_locale_choice_in_db
|
40
|
+
compute_effective_locale do |requested_locale|
|
41
|
+
if current_user
|
42
|
+
current_user.update_attribute 'preferred_locale', requested_locale
|
43
|
+
current_user.reload
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
...
|
48
|
+
|
49
|
+
|
50
|
+
== Initializer
|
51
|
+
|
52
|
+
The default text domain can be set in a initializer
|
53
|
+
file config/initializers/gettext.rb
|
54
|
+
|
55
|
+
LocaleSelector::default_domain = 'myapp'
|
56
|
+
|
57
|
+
== View
|
58
|
+
|
59
|
+
In app/views/layouts/application.html.erb or in single views you
|
60
|
+
can use
|
61
|
+
|
62
|
+
<%= language_selector %>
|
63
|
+
|
64
|
+
Or write your own language selector helper. For the example
|
65
|
+
see the documentation for language_selector method for an implementation
|
66
|
+
example.
|
67
|
+
=end
|
68
|
+
|
69
|
+
module LocaleSelector
|
70
|
+
|
71
|
+
# Please set the gettext domain in a initializer,
|
72
|
+
# the file <tt>config/initializers/gettext.rb</tt> is recommended
|
73
|
+
# LocaleSelector::default_domain = 'myapp'
|
74
|
+
def self.default_domain=(d)
|
75
|
+
@@default_domain = d
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.default_domain
|
79
|
+
defined?(@@default_domain) ? @@default_domain : 'default'
|
80
|
+
end
|
81
|
+
|
82
|
+
module ControllerClassMethods
|
83
|
+
# Usage:
|
84
|
+
# offer_locales :en_UK, :de, :domain => 'my_application'
|
85
|
+
# The default for the list of the locales is the list
|
86
|
+
# of subdirectories of the 'locale' folder.
|
87
|
+
# Possible options are:
|
88
|
+
# <tt>:domain</tt>::
|
89
|
+
# the gettext domain
|
90
|
+
# <tt>:lang_cookie_path</tt>::
|
91
|
+
# the path for cookie that remembers the user locale selection
|
92
|
+
def offer_locales(*args)
|
93
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
94
|
+
class_variable_set :@@offered_locales,
|
95
|
+
args.empty? ?
|
96
|
+
GetText::Rails::available_locales :
|
97
|
+
args.flatten.map{|l| l.to_s}.uniq
|
98
|
+
helper_method :effective_locale, :offered_locales
|
99
|
+
init_gettext options[:domain] || LocaleSelector::default_domain
|
100
|
+
class_variable_set :@@lang_cookie_path, options[:lang_cookie_path] || '/'
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def global_offered_locales # :nodoc:
|
106
|
+
class_variable_get :@@offered_locales
|
107
|
+
end
|
108
|
+
|
109
|
+
def lang_cookie_path # :nodoc:
|
110
|
+
class_variable_get :@@lang_cookie_path
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
module ControllerInstanceMethods
|
116
|
+
# List of explicitely offered locales, as set during the
|
117
|
+
# initialization by #offer_locales
|
118
|
+
def offered_locales
|
119
|
+
self.class.send :global_offered_locales
|
120
|
+
end
|
121
|
+
|
122
|
+
# This helper saves the user locale selection in a cookie.
|
123
|
+
# You can adjust the cookie path during the initialization
|
124
|
+
# with #offer_locales, use the :lang_cookie_path option.
|
125
|
+
def save_cookie(requested_lang)
|
126
|
+
cookies[:lang] = {
|
127
|
+
:value => requested_lang,
|
128
|
+
:expires => 1.month.from_now,
|
129
|
+
:path => root_path
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
# Accepts a block. The locale, conciously chosen by user
|
136
|
+
# is passed to the block. Can be used for persisting the
|
137
|
+
# user choice in a database or/and in a cookie.
|
138
|
+
def compute_effective_locale
|
139
|
+
# Priority order:
|
140
|
+
# 1.query parameter 'lang'
|
141
|
+
# 2.cookie 'lang'
|
142
|
+
# 3.browser setting
|
143
|
+
requested_lang = params[:lang] || cookies[:lang]
|
144
|
+
if self.offered_locales.include? requested_lang
|
145
|
+
yield requested_lang if block_given?
|
146
|
+
return requested_lang
|
147
|
+
end
|
148
|
+
|
149
|
+
parse_and_match_accept_language || 'en'
|
150
|
+
end
|
151
|
+
|
152
|
+
def parse_and_match_accept_language # :nodoc:
|
153
|
+
parsed = parse_accept_language(request.headers['Accept-language'])
|
154
|
+
match_accept_language parsed, offered_locales
|
155
|
+
end
|
156
|
+
|
157
|
+
def parse_accept_language(s) # :nodoc:
|
158
|
+
return [] unless s
|
159
|
+
res = []
|
160
|
+
s.split(',').each do |entry|
|
161
|
+
code, prio = entry.split(';q=')
|
162
|
+
res << [code, prio ? prio.to_f : 1]
|
163
|
+
end
|
164
|
+
res.sort {|a,b| b[1] <=> a[1]}
|
165
|
+
end
|
166
|
+
|
167
|
+
def match_accept_language(parsed_accept_language, offered_langs) # :nodoc:
|
168
|
+
parsed_accept_language.each do |lang, prio|
|
169
|
+
return lang if offered_langs.include?(lang)
|
170
|
+
return lang[0..1] if offered_langs.include?(lang[0..1])
|
171
|
+
end
|
172
|
+
offered_langs[0]
|
173
|
+
end
|
174
|
+
|
175
|
+
alias effective_locale compute_effective_locale
|
176
|
+
public :effective_locale
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
module ViewInstanceMethods
|
181
|
+
# Simple text based UI element for locale/language selection, that
|
182
|
+
# you can put on every page by calling this method in your layout view.
|
183
|
+
# Lists the languages offered by application as clickable links.
|
184
|
+
# see also #offer_locales.
|
185
|
+
#
|
186
|
+
# You can provide a block (executed per language) if you would
|
187
|
+
# like to override the default list of text based \<a href=""\> elements.
|
188
|
+
#
|
189
|
+
# For example, you can easily implement an image based language selector
|
190
|
+
# language_selector do |lang, active|
|
191
|
+
# link_to image_tag("#{lang}#{active ? '' : '_inactive'}.png", :alt => lang),
|
192
|
+
# language_selector_href(lang, params)
|
193
|
+
# end
|
194
|
+
def language_selector(additional_params=params, &block)
|
195
|
+
content_tag :ul, :id => 'language_selector' do
|
196
|
+
offered_locales.map do |lang|
|
197
|
+
selected = lang == effective_locale
|
198
|
+
content_tag :li, :class => "#{lang} #{selected ? 'selected' : ''}" do
|
199
|
+
if block_given?
|
200
|
+
yield lang, selected
|
201
|
+
else
|
202
|
+
link_to(lang, language_selector_href(lang, additional_params))
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end.join
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Can be used if you are going to implement your own language selection control.
|
210
|
+
# Generates a link, that links to the current page but with an additional
|
211
|
+
# 'lang' parameter.
|
212
|
+
#
|
213
|
+
# Note: if the user fills in e.g. form fields and clicks the language
|
214
|
+
# selection link afterwards, then the filled in data is lost.
|
215
|
+
def language_selector_href(lang, params)
|
216
|
+
path = (uri = request.request_uri) ? uri.split('?').first.to_s : ''
|
217
|
+
q = request.query_parameters.merge({'lang' => "#{lang}"}).map {
|
218
|
+
|k,v| "#{URI.escape(k.to_s)}=#{URI.escape(v.to_s)}" }.sort.join("&")
|
219
|
+
"#{path}?#{q}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
if defined?(ActionController)
|
225
|
+
ActionController::Base.send(:include, LocaleSelector::ControllerInstanceMethods)
|
226
|
+
ActionController::Base.extend LocaleSelector::ControllerClassMethods
|
227
|
+
end
|
228
|
+
if defined?(ActionView)
|
229
|
+
ActionView::Base.send(:include, LocaleSelector::ViewInstanceMethods)
|
230
|
+
end
|
231
|
+
|
232
|
+
module Locale # :nodoc:
|
233
|
+
# Patch for the gettext gem 1.92 and earlier.
|
234
|
+
# Now incorporated into gettext.
|
235
|
+
class Object
|
236
|
+
def self.parse(locale_name) # :nodoc:
|
237
|
+
# PATCH: the following line is new
|
238
|
+
locale_name = "en" if locale_name.nil? || locale_name.empty?
|
239
|
+
|
240
|
+
lang_charset, modifier = locale_name.split(/@/)
|
241
|
+
lang, charset = lang_charset.split(/\./)
|
242
|
+
language, country, script, variant = lang.gsub(/_/, "-").split('-')
|
243
|
+
language = language ? language.downcase : nil
|
244
|
+
language = "en" if language == "c" || language == "posix"
|
245
|
+
if country
|
246
|
+
if country =~ /\A[A-Z][a-z]+\Z/ #Latn => script
|
247
|
+
tmp = script
|
248
|
+
script = country
|
249
|
+
if tmp =~ /\A[A-Z]+\Z/ #US => country
|
250
|
+
country = tmp
|
251
|
+
else
|
252
|
+
country = nil
|
253
|
+
variant = tmp
|
254
|
+
end
|
255
|
+
else
|
256
|
+
country = country.upcase
|
257
|
+
if script !~ /\A[A-Z][a-z]+\Z/ #Latn => script
|
258
|
+
variant = script
|
259
|
+
script = nil
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
[language, country, charset, script, variant, modifier]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
SPEC = Gem::Specification.new do |s|
|
2
|
+
s.name = 'locale_selector'
|
3
|
+
s.version = '1.93.0'
|
4
|
+
s.summary = 'Wraps and improves ruby-gettext, provides UI for locale selection, maintains user preferences.'
|
5
|
+
s.description = s.summary
|
6
|
+
s.author = 'Vladimir Dobriakov'
|
7
|
+
s.email = 'vd_extern@vfnet.de'
|
8
|
+
s.homepage = 'http://github.com/geekq/locale_selector'
|
9
|
+
s.files = %w(MIT-LICENSE README.rdoc Rakefile TESTING.rdoc init.rb install.rb locale_selector.gemspec uninstall.rb) +
|
10
|
+
Dir.glob("{generators,lib,tasks,rails}/**/*")
|
11
|
+
|
12
|
+
Dir.glob("{generators,lib,tasks}/**/*")
|
13
|
+
s.require_path = "lib"
|
14
|
+
s.bindir = "bin"
|
15
|
+
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.extra_rdoc_files = ['README.rdoc', 'TESTING.rdoc', 'MIT-LICENSE']
|
18
|
+
s.rdoc_options = ['--line-numbers', '--inline-source', '--promiscuous', '--main', 'README.rdoc']
|
19
|
+
s.add_dependency 'gettext', '1.93.0'
|
20
|
+
s.rubyforge_project = 'locale_selector'
|
21
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'locale_selector'
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: locale_selector
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.93.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vladimir Dobriakov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-02 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: gettext
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.93.0
|
24
|
+
version:
|
25
|
+
description: Wraps and improves ruby-gettext, provides UI for locale selection, maintains user preferences.
|
26
|
+
email: vd_extern@vfnet.de
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
- TESTING.rdoc
|
34
|
+
- MIT-LICENSE
|
35
|
+
files:
|
36
|
+
- MIT-LICENSE
|
37
|
+
- README.rdoc
|
38
|
+
- Rakefile
|
39
|
+
- TESTING.rdoc
|
40
|
+
- init.rb
|
41
|
+
- install.rb
|
42
|
+
- locale_selector.gemspec
|
43
|
+
- uninstall.rb
|
44
|
+
- generators/gettext_hacks
|
45
|
+
- generators/gettext_hacks/templates
|
46
|
+
- generators/gettext_hacks/templates/gettext_hacks.rb
|
47
|
+
- generators/gettext_hacks/gettext_hacks_generator.rb
|
48
|
+
- lib/locale_selector
|
49
|
+
- lib/locale_selector/gettext_tasks.rb
|
50
|
+
- lib/locale_selector.rb
|
51
|
+
- rails/init.rb
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/geekq/locale_selector
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options:
|
56
|
+
- --line-numbers
|
57
|
+
- --inline-source
|
58
|
+
- --promiscuous
|
59
|
+
- --main
|
60
|
+
- README.rdoc
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
requirements: []
|
76
|
+
|
77
|
+
rubyforge_project: locale_selector
|
78
|
+
rubygems_version: 1.3.1
|
79
|
+
signing_key:
|
80
|
+
specification_version: 2
|
81
|
+
summary: Wraps and improves ruby-gettext, provides UI for locale selection, maintains user preferences.
|
82
|
+
test_files: []
|
83
|
+
|