merb_babel 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +151 -0
- data/Rakefile +58 -0
- data/TODO +5 -0
- data/lib/merb_babel.rb +59 -0
- data/lib/merb_babel/locale_detector.rb +80 -0
- data/lib/merb_babel/m_i18n.rb +39 -0
- data/lib/merb_babel/m_l10n.rb +149 -0
- data/lib/merb_babel/m_locale.rb +103 -0
- data/lib/merb_babel/merbtasks.rb +6 -0
- data/spec/lang/en-UK.yml +13 -0
- data/spec/lang/en-US.yml +13 -0
- data/spec/lang/en.yml +22 -0
- data/spec/lang/ja.yml +23 -0
- data/spec/locale_detector_spec.rb +42 -0
- data/spec/m_i18n_spec.rb +75 -0
- data/spec/m_l10n_spec.rb +54 -0
- data/spec/merb_babel_spec.rb +127 -0
- data/spec/other_lang_dir/fr.yml +14 -0
- data/spec/spec_helper.rb +50 -0
- metadata +96 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Matt Aimonetti
|
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.markdown
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
Merb_babel
|
2
|
+
=========
|
3
|
+
|
4
|
+
A plugin for the Merb framework that provides locales, languages, countries. (in a thread safe environment)
|
5
|
+
|
6
|
+
|
7
|
+
Purpose of Merb\_babel
|
8
|
+
---------------------
|
9
|
+
|
10
|
+
Merb_babel is primarily written to fulfill my personal needs. Instead of porting my http://github.com/mattetti/globalite plugin over, I decided to re write it from scratch learning from my mistakes.
|
11
|
+
|
12
|
+
Goals:
|
13
|
+
|
14
|
+
* simplicity
|
15
|
+
* speed
|
16
|
+
|
17
|
+
My first and simple objective is to get Merb to work in Simplified and Traditional Chinese + switch from one to the other.
|
18
|
+
|
19
|
+
Also, as of today, I'm not planning on supporting model localization since I believe it's easy to do, and in most cases it's too specific to use a plugin. (but other plugins offer that for you anyway ;) )
|
20
|
+
|
21
|
+
One of the objectives is that people can add Merb\_babel to their project and use merb in a different language without worrying about internationalization/localization. I hope to keep merb helpers and other plugins (merb\_activerecord / merb\_datamapper / merb\_sequel) localized so someone can define his app's locale/language/country and Merb will talk his language right away.
|
22
|
+
|
23
|
+
Before you go further, you might want to read [this explanation about i18n/l10n](http://www.w3.org/International/questions/qa-i18n)
|
24
|
+
|
25
|
+
Usage
|
26
|
+
------
|
27
|
+
|
28
|
+
In your application controller add:
|
29
|
+
|
30
|
+
before :set_locale
|
31
|
+
|
32
|
+
|
33
|
+
and access the user locale using @controller.locale (or simply #locale in the controller)
|
34
|
+
If a locale is set, you can also access @controller.language and @controller.country (same thing, you can use #language or #country from within your controller scope)
|
35
|
+
|
36
|
+
The locale is stored in request.env[:locale]
|
37
|
+
|
38
|
+
At the moment you have 3 ways of setting up a locale:
|
39
|
+
|
40
|
+
* default way in the config settings (that you can overwrite in your init.rb file )
|
41
|
+
|
42
|
+
Merb::Plugins.config[:Merb_babel] = {
|
43
|
+
:default_locale => 'en-US',
|
44
|
+
:default_language => 'en',
|
45
|
+
:default_country => 'US'
|
46
|
+
}
|
47
|
+
|
48
|
+
* per request basis, by sending a param called locale (language, and country will set their own values)
|
49
|
+
* store the locale in the session
|
50
|
+
* use routes
|
51
|
+
|
52
|
+
Babel doesn't support http header lookup yet.
|
53
|
+
|
54
|
+
Set locale in your routes
|
55
|
+
--------------------------
|
56
|
+
|
57
|
+
r.match(/\/?(en\-US|en\-UK|es\-ES|es\-AR)?/).to(:locale => "[1]") do |l|
|
58
|
+
l.match("/articles/:action/:id").to(:controller => "articles")
|
59
|
+
end
|
60
|
+
|
61
|
+
What if you don't need to use a full locale?
|
62
|
+
--------------------------------------------
|
63
|
+
|
64
|
+
some people might not need to use the full locale, they just want to use one version of a language and the locale is an overkill. Don't worry, you can use the language instance variable.
|
65
|
+
|
66
|
+
before :set_language
|
67
|
+
|
68
|
+
|
69
|
+
All locale work is done in ``merb_babel/lib/merb_babel/m_locale.rb`` and tested in ``spec/merb_babel_spec.rb``
|
70
|
+
|
71
|
+
Localization(L10n)
|
72
|
+
------------------
|
73
|
+
|
74
|
+
L10n is basically the adaptation of your product to a specific locale. In our case, we see L10n as the storing and retrieval of localized data. (for a locale or language)
|
75
|
+
|
76
|
+
Localizations are loaded from localization files.
|
77
|
+
|
78
|
+
Localization files are simple yaml files that get loaded in memory. By default Merb\_babel will look in ./lang for localization files. The default location is defined in Merb::Plugins.config[:merb_babel][:localization_dirs] and can be overwritten. Also, you can add more folders to look for by calling:
|
79
|
+
|
80
|
+
add_localization_dir(path_with_more_localization_files)
|
81
|
+
|
82
|
+
Note: when you add a new localization directory, localizations gets reloaded.
|
83
|
+
This needs to be done when Merb loads as I didn't add a mutex around that task yet.
|
84
|
+
|
85
|
+
Localizations are available in #localizations and are namespaced as follows:
|
86
|
+
|
87
|
+
localizations['en'][:right] => 'right'
|
88
|
+
localizations['en'][:left] => 'left'
|
89
|
+
localizations['en']['US'][:greeting] => 'Howdie'
|
90
|
+
localizations['en']['AU'][:greeting] => "Good'ay"
|
91
|
+
|
92
|
+
For that the localization files to be loaded properly, you need to follow some conventions:
|
93
|
+
|
94
|
+
* you have to declare a merb localization language code pair:
|
95
|
+
mloc\_language_code: en
|
96
|
+
where en represents the language code of the localization
|
97
|
+
|
98
|
+
* All generic localization for a language should go under their own language file. Region/culture specific localizations have to go to their own files and will be used if the full locale is set.
|
99
|
+
|
100
|
+
* A localization file is recognized as being locale specific if the mloc_country_code pair is set.
|
101
|
+
|
102
|
+
* ONLY localizations/translations specific to a locale should be written in a locale file.
|
103
|
+
|
104
|
+
* Recommended: set the mloc\_language_name pair so you list the available languages in their own language.
|
105
|
+
|
106
|
+
* look at examples in spec/lang
|
107
|
+
|
108
|
+
All the Localization(L10n) work is done in ``merb_babel/lib/merb_abel/m_l10n.rb`` and tested in ``spec/m_l10n_spec.rb``
|
109
|
+
|
110
|
+
|
111
|
+
Internationalization(I18n)
|
112
|
+
--------------------------
|
113
|
+
|
114
|
+
I18n enables easy localization of your product. That's what the developer/designer user to make their data localizable.
|
115
|
+
|
116
|
+
At the moment, only strings can be localized/translated.
|
117
|
+
|
118
|
+
In your controller, or view simply do:
|
119
|
+
|
120
|
+
translate(:localization_key)
|
121
|
+
|
122
|
+
You might prefer a shorter version so here are some aliases for you to use:
|
123
|
+
|
124
|
+
babelize(:translation_key)
|
125
|
+
or
|
126
|
+
t(:translation_key)
|
127
|
+
or
|
128
|
+
_(:translation_key)
|
129
|
+
|
130
|
+
The translation will use the full locale (language and country) if set and available, otherwise the language translation will be displayed.
|
131
|
+
|
132
|
+
*Params*
|
133
|
+
|
134
|
+
You can pass a hash of parameters after the translation key. For instance:
|
135
|
+
|
136
|
+
t(:greetings, :language => 'fr')
|
137
|
+
|
138
|
+
Would lookup the French translation for the greetings key and return 'Salut'
|
139
|
+
|
140
|
+
You can also pass the country code to use the full locale.
|
141
|
+
|
142
|
+
t(:greetings, :language => 'en', :country => 'AU')
|
143
|
+
|
144
|
+
would lookup the Australian English translation for the greetings key and return "G'day"
|
145
|
+
|
146
|
+
|
147
|
+
Other plugins you might want to look at:
|
148
|
+
----------------------------------------
|
149
|
+
|
150
|
+
* http://github.com/myabc/merb_global
|
151
|
+
* http://github.com/lemon/poppycock
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
require 'merb-core'
|
5
|
+
require 'merb-core/tasks/merb'
|
6
|
+
|
7
|
+
GEM_NAME = "merb_babel"
|
8
|
+
GEM_VERSION = "0.1.2"
|
9
|
+
AUTHOR = "Matt Aimonetti"
|
10
|
+
EMAIL = "mattaimonetti@gmail.com"
|
11
|
+
HOMEPAGE = "http://github.com/mattetti/merb_babel/"
|
12
|
+
SUMMARY = "Merb plugin that provides simple localization/internationalisation"
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.rubyforge_project = 'merb'
|
16
|
+
s.name = GEM_NAME
|
17
|
+
s.version = GEM_VERSION
|
18
|
+
s.platform = Gem::Platform::RUBY
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.extra_rdoc_files = ["README.markdown", "LICENSE", 'TODO']
|
21
|
+
s.summary = SUMMARY
|
22
|
+
s.description = s.summary
|
23
|
+
s.author = AUTHOR
|
24
|
+
s.email = EMAIL
|
25
|
+
s.homepage = HOMEPAGE
|
26
|
+
s.add_dependency('merb-core', '>= 1.0')
|
27
|
+
s.add_dependency('locale', '>= 0.9.0')
|
28
|
+
s.require_path = 'lib'
|
29
|
+
s.files = %w(LICENSE README.markdown Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
|
30
|
+
end
|
31
|
+
|
32
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
33
|
+
pkg.gem_spec = spec
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "install the plugin as a gem"
|
37
|
+
task :install do
|
38
|
+
Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Uninstall the gem"
|
42
|
+
task :uninstall do
|
43
|
+
Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Create a gemspec file"
|
47
|
+
task :gemspec do
|
48
|
+
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
49
|
+
file.puts spec.to_ruby
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Run specs"
|
54
|
+
task :spec do
|
55
|
+
sh "spec --color spec"
|
56
|
+
end
|
57
|
+
|
58
|
+
task :default => :spec
|
data/TODO
ADDED
data/lib/merb_babel.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#require File.join(File.dirname(__FILE__) / "merb_babel" / "core_ext")
|
2
|
+
|
3
|
+
# make sure we're running inside Merb
|
4
|
+
if defined?(Merb::Plugins)
|
5
|
+
|
6
|
+
# Merb gives you a Merb::Plugins.config hash...feel free to put your stuff in your piece of it
|
7
|
+
Merb::Plugins.config[:merb_babel] = {
|
8
|
+
:default_locale => 'en-US',
|
9
|
+
:default_language => 'en',
|
10
|
+
# :default_country => 'US',
|
11
|
+
:localization_dirs => ["#{Merb.root}/lang"]
|
12
|
+
}
|
13
|
+
|
14
|
+
require File.join(File.dirname(__FILE__) / "merb_babel" / "m_locale")
|
15
|
+
require File.join(File.dirname(__FILE__) / "merb_babel" / "m_l10n")
|
16
|
+
require File.join(File.dirname(__FILE__) / "merb_babel" / "m_i18n")
|
17
|
+
require File.join(File.dirname(__FILE__) / "merb_babel" / 'locale_detector')
|
18
|
+
gem "locale"
|
19
|
+
require 'locale'
|
20
|
+
|
21
|
+
Merb::BootLoader.before_app_loads do
|
22
|
+
# require code that must be loaded before the application
|
23
|
+
module Merb
|
24
|
+
module GlobalHelpers
|
25
|
+
|
26
|
+
# Used to translate words using localizations
|
27
|
+
def babelize(*args)
|
28
|
+
begin
|
29
|
+
options = args.pop if args.last.kind_of?(Hash)
|
30
|
+
options ||= {}
|
31
|
+
options[:language] ||= language
|
32
|
+
options[:country] ||= country
|
33
|
+
case key = args.last
|
34
|
+
when Date, Time
|
35
|
+
format = MI18n.lookup(options.merge(:keys => args[0..-2]))
|
36
|
+
ML10n.localize_time(key, format, options)
|
37
|
+
else
|
38
|
+
MI18n.lookup(options.merge(:keys => args))
|
39
|
+
end
|
40
|
+
rescue
|
41
|
+
key.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
alias :translate :babelize
|
45
|
+
alias :t :babelize
|
46
|
+
alias :_ :babelize
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Merb::Controller.send(:include, MLocale)
|
51
|
+
ML10n.load_localization!
|
52
|
+
end
|
53
|
+
|
54
|
+
Merb::BootLoader.after_app_loads do
|
55
|
+
# code that can be required after the application loads
|
56
|
+
end
|
57
|
+
|
58
|
+
Merb::Plugins.add_rakefiles "merb_babel/merbtasks"
|
59
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module LocaleDetector
|
2
|
+
LANGUAGE_TO_COUNTRY = {
|
3
|
+
"nn"=>["NO"],
|
4
|
+
"uk"=>["UA"],
|
5
|
+
"it"=>["IT", "GI", "CH", "LY", "SM"],
|
6
|
+
"zh_TW"=>["TT", "VN", "HK"],
|
7
|
+
"no"=>["NO"],
|
8
|
+
"st"=>["ZA"],
|
9
|
+
"tk"=>["TM"],
|
10
|
+
"bn"=>["IN"],
|
11
|
+
"mn"=>["MN"],
|
12
|
+
"ja"=>["JP"],
|
13
|
+
"fr"=>["FR", "CD", "GG", "RW", "CG", "LU", "TT", "CH", "CI", "JE", "SC",
|
14
|
+
"VN", "BE", "MU", "DJ", "BI", "CA"],
|
15
|
+
"hi"=>["TT", "AE", "IN"],
|
16
|
+
"de"=>["DE", "LU", "CH", "LI", "AT", "BE", "RO"],
|
17
|
+
"ne"=>["NP"], "jw"=>["ID"],
|
18
|
+
"ta"=>["IN", "SG"],
|
19
|
+
"tl"=>["PH"],
|
20
|
+
"pt_PT"=>["PT", "GI"],
|
21
|
+
"hu"=>["HU", "SK", "RO"],
|
22
|
+
"sk"=>["SK"],
|
23
|
+
"fi"=>["FI"],
|
24
|
+
"sv"=>["SE", "FI"],
|
25
|
+
"iw"=>["IL"],
|
26
|
+
"az"=>["AZ"],
|
27
|
+
"zh"=>["TW"],
|
28
|
+
"ru"=>["RU", "KZ", "KG", "AZ", "LV", "UA", "TM", "AM", "UZ"],
|
29
|
+
"ky"=>["KG"],
|
30
|
+
"es"=>["ES", "HN", "CU", "PR", "TT", "PA", "VE", "DO", "BO", "GI", "PE",
|
31
|
+
"PY", "NI", "CL", "SV", "CO", "UY", "BZ", "CR", "EC", "GT", "AR", "MX"],
|
32
|
+
"ko"=>["KR"],
|
33
|
+
"pt_BR"=>["BR"],
|
34
|
+
"sw"=>["RW", "KE"],
|
35
|
+
"ga"=>["IE"],
|
36
|
+
"id"=>["ID"],
|
37
|
+
"eu"=>["ES"],
|
38
|
+
"gl"=>["ES"],
|
39
|
+
"xh"=>["ZA"],
|
40
|
+
"uz"=>["TM", "UZ"],
|
41
|
+
"mr"=>["IN"],
|
42
|
+
"fa"=>["AE"],
|
43
|
+
"zu"=>["LS", "ZA"],
|
44
|
+
"af"=>["NA", "ZA"],
|
45
|
+
"pl"=>["PL"],
|
46
|
+
"hy"=>["AM"],
|
47
|
+
"pa"=>["PK"],
|
48
|
+
"te"=>["IN"],
|
49
|
+
"ar"=>["AE", "LY", "SA", "DJ"],
|
50
|
+
"ms"=>["MY", "SG"],
|
51
|
+
"el"=>["GR"],
|
52
|
+
"ro"=>["RO"],
|
53
|
+
"mt"=>["MT"],
|
54
|
+
"ur"=>["AE", "PK"],
|
55
|
+
"da"=>["DK", "GL"],
|
56
|
+
"ca"=>["ES"],
|
57
|
+
"tr"=>["TR"],
|
58
|
+
"zh_CN"=>["SG"],
|
59
|
+
"nl"=>["NL", "BE", "ID"],
|
60
|
+
"vi"=>["VN"],
|
61
|
+
"lt"=>["LT", "LV"],
|
62
|
+
"th"=>["TH"],
|
63
|
+
"fo"=>["DK"],
|
64
|
+
"en"=>["US", "AS", "IE", "NP", "MY", "UK", "FM", "VC", "PR", "TT", "AU",
|
65
|
+
"PA", "NA", "GG", "LS", "RW", "VG", "AE", "GI", "VI", "AG", "TH", "CH",
|
66
|
+
"NF", "JE", "AI", "GL", "PH", "CK", "GM", "LY", "IN", "NZ", "NI", "SC",
|
67
|
+
"PK", "VN", "MS", "TO", "MT", "BE", "PN", "MU", "UG", "SG", "ZA", "BZ",
|
68
|
+
"SH", "MW", "FJ", "CR", "HK", "JM", "KE", "CA", "ID"],
|
69
|
+
"lv"=>["LV"]
|
70
|
+
}.freeze
|
71
|
+
|
72
|
+
module_function
|
73
|
+
def countries_from_language(language)
|
74
|
+
LANGUAGE_TO_COUNTRY[language]
|
75
|
+
end
|
76
|
+
|
77
|
+
def country_from_language(language)
|
78
|
+
(countries_from_language(language) || []).first
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module MI18n
|
2
|
+
|
3
|
+
def self.lookup(options)
|
4
|
+
keys = [options[:keys].map{|key| key.to_s}].flatten
|
5
|
+
language = options[:language]
|
6
|
+
country = options[:country]
|
7
|
+
|
8
|
+
raise ArgumentError, "You need to pass a language reference" unless language
|
9
|
+
raise ArgumentError, "You need to pass a localization key" if keys.empty?
|
10
|
+
raise ArgumentError,
|
11
|
+
"language: #{language} not found" unless ML10n.localizations[language]
|
12
|
+
|
13
|
+
full_location = nil
|
14
|
+
full_location = lookup_with_full_locale(keys, language, country) if country
|
15
|
+
|
16
|
+
if full_location
|
17
|
+
return full_location
|
18
|
+
else
|
19
|
+
return lookup_with_language(keys, language) || keys.last
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.lookup_with_language(keys, language)
|
24
|
+
lookup_with_hash(keys, ML10n.localizations[language])
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.lookup_with_full_locale(keys, language, country)
|
28
|
+
if ML10n.localizations.has_key?(language)
|
29
|
+
ML10n.localizations[language].has_key?(country) ?
|
30
|
+
lookup_with_hash(keys, ML10n.localizations[language][country]) : nil
|
31
|
+
else
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.lookup_with_hash(keys, l_hash)
|
37
|
+
keys.inject(l_hash){|h,k| h[k] rescue nil}
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module ML10n
|
2
|
+
LANGUAGE_CODE_KEY = 'mloc_language_code'.freeze
|
3
|
+
COUNTRY_CODE_KEY = 'mloc_country_code'.freeze
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# TODO add a mutex for when we load the localizations, in case people want to load the localizations
|
8
|
+
# at runtime
|
9
|
+
|
10
|
+
# all localizations are saved in this class variable
|
11
|
+
# localizations are namespaced using the language or locale they belong to
|
12
|
+
#
|
13
|
+
# for instance:
|
14
|
+
# ML10n.localizations['en'][:right] => 'right'
|
15
|
+
# ML10n.localizations['en'][:left] => 'left'
|
16
|
+
# ML10n.localizations['en']['US'][:greeting] => 'Howdie'
|
17
|
+
# ML10n.localizations['en']['AU'][:greeting] => "Good'ay"
|
18
|
+
#
|
19
|
+
# locales, including languages and countries use string keys while localization keys themselves are symbols
|
20
|
+
def localizations
|
21
|
+
@@localizations ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
# files containing localizations
|
25
|
+
def localization_files
|
26
|
+
@@localization_files ||= ML10n.find_localization_files
|
27
|
+
end
|
28
|
+
|
29
|
+
# locations to look for localization files
|
30
|
+
def localization_dirs
|
31
|
+
@@localization_dirs ||= Merb::Plugins.config[:merb_babel][:localization_dirs].dup
|
32
|
+
end
|
33
|
+
|
34
|
+
# add a dir to look for localizations
|
35
|
+
def add_localization_dir(dir_path)
|
36
|
+
return ML10n.localization_dirs if dir_path.empty?
|
37
|
+
unless ML10n.localization_dirs.include?(dir_path)
|
38
|
+
ML10n.localization_dirs << dir_path
|
39
|
+
ML10n.reload_localization_files!
|
40
|
+
end
|
41
|
+
return ML10n.localization_dirs
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_localization!
|
45
|
+
|
46
|
+
# look for localization files directly just in case new files were added
|
47
|
+
ML10n.reset_localization_files!
|
48
|
+
ML10n.find_localization_files.each do |l_file|
|
49
|
+
begin
|
50
|
+
l_hash = YAML.load_file(l_file)#.symbolize_keys
|
51
|
+
rescue Exception => e
|
52
|
+
# might raise a real error here in the future
|
53
|
+
p e.inspect
|
54
|
+
else
|
55
|
+
load_localization_hash(l_hash)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
# go through the localization dirs and find the localization files
|
62
|
+
def find_localization_files
|
63
|
+
l_files = []
|
64
|
+
ML10n.localization_dirs.map do |l_dir|
|
65
|
+
Dir["#{l_dir}/*"].each do |file|
|
66
|
+
l_files << file unless l_files.include?(file)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
return l_files
|
70
|
+
end
|
71
|
+
|
72
|
+
# reset the localization dirs and files to the plugin config
|
73
|
+
# careful when using this method since it will remove any localization files
|
74
|
+
# you loaded after the plugin started
|
75
|
+
#
|
76
|
+
# note that it won't clear the localization already loaded in memory
|
77
|
+
def reset_localization_files_and_dirs!
|
78
|
+
ML10n.reset_localization_dirs!
|
79
|
+
ML10n.reset_localization_files!
|
80
|
+
end
|
81
|
+
|
82
|
+
def reset_localization_dirs!
|
83
|
+
@@localization_dirs = nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def reset_localization_files!
|
87
|
+
@@localization_files = nil
|
88
|
+
ML10n.find_localization_files
|
89
|
+
end
|
90
|
+
|
91
|
+
def reset_localizations!
|
92
|
+
@@localizations = {}
|
93
|
+
end
|
94
|
+
|
95
|
+
def reload_localization_files!
|
96
|
+
ML10n.reset_localization_files!
|
97
|
+
ML10n.find_localization_files
|
98
|
+
end
|
99
|
+
|
100
|
+
# localization helper
|
101
|
+
def localize(key, *options)
|
102
|
+
MI18n.localize(options.merge({:locale => locale}))
|
103
|
+
end
|
104
|
+
|
105
|
+
def localize_time(object, format, options)
|
106
|
+
table_for = proc do |table_name, key, default|
|
107
|
+
keys = ["DateFormat", table_name]
|
108
|
+
table = MI18n.lookup(options.merge(:keys => keys)) || {}
|
109
|
+
table[key] || default
|
110
|
+
end
|
111
|
+
format = format.to_s.dup
|
112
|
+
format.gsub!(/%a/) do
|
113
|
+
table_for["AbbrDayNames", object.wday, "%a"]
|
114
|
+
end
|
115
|
+
format.gsub!(/%A/) do
|
116
|
+
table_for["AbbrMonthNames", object.mon - 1, "%A"]
|
117
|
+
end
|
118
|
+
format.gsub!(/%B/) do
|
119
|
+
table_for["MonthNames", object.mon - 1, "%B"]
|
120
|
+
end
|
121
|
+
format.gsub!(/%p/) do
|
122
|
+
table_for["AmPm", object.hour < 12 ? 0 : 1, "%p"]
|
123
|
+
end if object.respond_to?(:hour)
|
124
|
+
format.gsub!(/%\{([a-zA-Z]\w*)\}/) do
|
125
|
+
object.send($1) rescue $1
|
126
|
+
end
|
127
|
+
object.strftime(format)
|
128
|
+
end
|
129
|
+
|
130
|
+
protected
|
131
|
+
|
132
|
+
def load_localization_hash(l_hash)
|
133
|
+
if l_hash.has_key?(LANGUAGE_CODE_KEY)
|
134
|
+
language = l_hash[LANGUAGE_CODE_KEY]
|
135
|
+
if l_hash.has_key?(COUNTRY_CODE_KEY)
|
136
|
+
country = l_hash[COUNTRY_CODE_KEY]
|
137
|
+
# load localization under the full locale namespace
|
138
|
+
ML10n.localizations[language] ||= {}
|
139
|
+
(ML10n.localizations[language][country] ||= {}).merge!(l_hash)
|
140
|
+
else
|
141
|
+
# load generic language localization
|
142
|
+
(ML10n.localizations[language] ||= {}).merge!(l_hash)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
|
2
|
+
# The MLocale module helps you set up a locale, language, country
|
3
|
+
# You don't have to use a locale, in some cases you might just want to use the language
|
4
|
+
module MLocale
|
5
|
+
def locale_from_request
|
6
|
+
if hal = request.env["HTTP_ACCEPT_LANGUAGE"]
|
7
|
+
hal.gsub!(/\s/, "")
|
8
|
+
result = hal.split(/,/).map do |v|
|
9
|
+
v.split(";q=")
|
10
|
+
end.map do |j|
|
11
|
+
[j[0], j[1] ? j[1].to_f : 1.0]
|
12
|
+
end.sort do |a,b|
|
13
|
+
-(a[1] <=> b[1])
|
14
|
+
end.map do |v|
|
15
|
+
Locale::Tag.parse(v[0])
|
16
|
+
end.first
|
17
|
+
return nil if result.nil?
|
18
|
+
language = result.language
|
19
|
+
country = result.country ||
|
20
|
+
LocaleDetector.country_from_language(language)
|
21
|
+
request.env[:locale] = "#{language}-#{country}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# A locale is made of a language + country code, such as en-UK or en-US
|
26
|
+
def locale
|
27
|
+
request.env[:locale] || params[:locale] || (session ? session[:locale] : nil) || locale_from_request || default_locale
|
28
|
+
end
|
29
|
+
|
30
|
+
# Many people don't care about locales, they might just want to use languages instead
|
31
|
+
def language
|
32
|
+
request.env[:language] || params[:language] || language_from_locale || (session ? session[:language] : nil) || default_language
|
33
|
+
end
|
34
|
+
|
35
|
+
# The country is used when localizing currency or time
|
36
|
+
def country
|
37
|
+
request.env[:country] || params[:country] || country_from_locale || (session ? session[:country] : nil) || LocaleDetector.country_from_language(language) || default_country
|
38
|
+
end
|
39
|
+
|
40
|
+
# Extract the language from the locale
|
41
|
+
def language_from_locale
|
42
|
+
if request.env[:locale] && request.env[:locale] =~ locale_regexp
|
43
|
+
language, country = request.env[:locale].match(locale_regexp).captures
|
44
|
+
return language
|
45
|
+
else
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Extract the country from the locale
|
51
|
+
def country_from_locale
|
52
|
+
request.env[:locale] ? request.env[:locale][3..5].upcase : nil
|
53
|
+
end
|
54
|
+
|
55
|
+
# Defaults set in the plugin settings
|
56
|
+
# You can change the default settings by overwriting
|
57
|
+
# the Merb::Plugins.config[:merb_abel] hash in your settings
|
58
|
+
#
|
59
|
+
def default_locale
|
60
|
+
Merb::Plugins.config[:merb_babel] ? Merb::Plugins.config[:merb_babel][:default_locale] : nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_language
|
64
|
+
Merb::Plugins.config[:merb_babel] ? Merb::Plugins.config[:merb_babel][:default_language] : nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_country
|
68
|
+
Merb::Plugins.config[:merb_babel] ? Merb::Plugins.config[:merb_babel][:default_country] : nil
|
69
|
+
end
|
70
|
+
#
|
71
|
+
#### end of defaults
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def locale_regexp
|
76
|
+
/(.+)\-([a-z]{2})/i
|
77
|
+
end
|
78
|
+
|
79
|
+
# You can extend this method in application.rb
|
80
|
+
# example:
|
81
|
+
#
|
82
|
+
# def set_locale
|
83
|
+
# super
|
84
|
+
# session[:language] = language
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
#
|
88
|
+
# takes a locale as in fr-FR or en-US
|
89
|
+
def set_locale
|
90
|
+
if locale =~ locale_regexp
|
91
|
+
language, country = locale.match(locale_regexp).captures
|
92
|
+
# Set the locale, language and country
|
93
|
+
language = language.downcase
|
94
|
+
country = country.upcase
|
95
|
+
request.env[:locale] = "#{language}-#{country}"
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
def set_language
|
101
|
+
request.env[:language] = language.downcase
|
102
|
+
end
|
103
|
+
end
|
data/spec/lang/en-UK.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#################################################
|
2
|
+
# en-UK only localization
|
3
|
+
#
|
4
|
+
# only add localization specific to this locale
|
5
|
+
# other comman localizations must go in en.yml
|
6
|
+
#################################################
|
7
|
+
# required
|
8
|
+
mloc_language_code: en
|
9
|
+
# required for a locale localization file
|
10
|
+
mloc_country_code: UK
|
11
|
+
#################################################
|
12
|
+
|
13
|
+
greetings: Heya
|
data/spec/lang/en-US.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#################################################
|
2
|
+
# en-US only localization
|
3
|
+
#
|
4
|
+
# only add localization specific to this locale
|
5
|
+
# other comman localizations must go in en.yml
|
6
|
+
#################################################
|
7
|
+
# required
|
8
|
+
mloc_language_code: en
|
9
|
+
# required for a locale localization file
|
10
|
+
mloc_country_code: US
|
11
|
+
#################################################
|
12
|
+
|
13
|
+
greetings: Howdie
|
data/spec/lang/en.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#################################################
|
2
|
+
# English localization
|
3
|
+
#
|
4
|
+
# localization specific must go in their own file
|
5
|
+
# see en-US.yml for instance
|
6
|
+
#################################################
|
7
|
+
mloc_language_code: en
|
8
|
+
# Optional, the following key has the name of the localized language in its ow language.
|
9
|
+
mloc_language_name: English
|
10
|
+
# mloc_country:
|
11
|
+
#################################################
|
12
|
+
|
13
|
+
|
14
|
+
right: right
|
15
|
+
left: left
|
16
|
+
greetings: Hello
|
17
|
+
|
18
|
+
night:
|
19
|
+
greetings: Good evening
|
20
|
+
|
21
|
+
DateFormat:
|
22
|
+
AbbrDayNames: ["S", "M", "T", "W", "T", "F", "S"]
|
data/spec/lang/ja.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#################################################
|
2
|
+
# Japanese localization
|
3
|
+
#
|
4
|
+
# localization specific must go in their own file
|
5
|
+
# see ja-JP.yml for instance
|
6
|
+
#################################################
|
7
|
+
mloc_language_code: ja
|
8
|
+
# Optional, the following key has the name of the localized language in its ow language.
|
9
|
+
mloc_language_name: Japanese
|
10
|
+
# mloc_country:
|
11
|
+
#################################################
|
12
|
+
|
13
|
+
|
14
|
+
right: 右
|
15
|
+
left: 左
|
16
|
+
greetings: こんにちわ
|
17
|
+
|
18
|
+
night:
|
19
|
+
greetings: こんばんわ
|
20
|
+
|
21
|
+
DateFormat:
|
22
|
+
AbbrDayNames: ["日", "月", "火", "水", "木", "金", "土"]
|
23
|
+
AmPm: ["午前", "午後"]
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'country detector' do
|
4
|
+
it "should detect country from request" do
|
5
|
+
c = dispatch_to(TestController, :index, {},
|
6
|
+
'HTTP_ACCEPT_LANGUAGE' => 'en-UK')
|
7
|
+
c.country.should == 'UK'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should detect language from request" do
|
11
|
+
c = dispatch_to(TestController, :index, {},
|
12
|
+
'HTTP_ACCEPT_LANGUAGE' => 'fr-FR')
|
13
|
+
c.language.should == 'fr'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should detect full locale from request" do
|
17
|
+
c = dispatch_to(TestController, :index, {},
|
18
|
+
'HTTP_ACCEPT_LANGUAGE' => 'en-UK')
|
19
|
+
c.locale.should == 'en-UK'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should detect full locale from request 2" do
|
23
|
+
c = dispatch_to(TestController, :index, {},
|
24
|
+
'HTTP_ACCEPT_LANGUAGE' => 'en_UK')
|
25
|
+
c.language.should == 'en'
|
26
|
+
c.country.should == 'UK'
|
27
|
+
c.locale.should == 'en-UK'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should guess country from language" do
|
31
|
+
c = dispatch_to(TestController, :index, {},
|
32
|
+
'HTTP_ACCEPT_LANGUAGE' => 'ja')
|
33
|
+
c.country.should == 'JP'
|
34
|
+
c.locale.should == 'ja-JP'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should detect language from request including candidates" do
|
38
|
+
c = dispatch_to(TestController, :index, {},
|
39
|
+
'HTTP_ACCEPT_LANGUAGE' => 'ja,en;q=0.9,fr;q=0.8,de;q=0.7,es;q=0.6')
|
40
|
+
c.locale.should == 'ja-JP'
|
41
|
+
end
|
42
|
+
end
|
data/spec/m_i18n_spec.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe '#babelize' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Merb::Controller.send :include, Merb::GlobalHelpers
|
7
|
+
@c = dispatch_to(TestController, :index)
|
8
|
+
ML10n.add_localization_dir(File.expand_path(File.dirname(__FILE__) + "/lang"))
|
9
|
+
ML10n.add_localization_dir(File.expand_path(File.dirname(__FILE__) + "/other_lang_dir"))
|
10
|
+
ML10n.load_localization!
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
ML10n.reset_localizations!
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should babelize a word in English " do
|
18
|
+
@c.locale.should == 'en-US'
|
19
|
+
@c.language.should == 'en'
|
20
|
+
@c.country.should == 'US'
|
21
|
+
@c.babelize(:left).should == 'left'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should translate a word in English" do
|
25
|
+
@c.t(:left).should == 'left'
|
26
|
+
@c.translate(:left).should == 'left'
|
27
|
+
@c._(:left).should == 'left'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should translate a word in american English" do
|
31
|
+
@c.t(:greetings).should == 'Howdie'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should translate a word in british English" do
|
35
|
+
@c.request.env[:locale] = 'en-UK'
|
36
|
+
@c.t(:greetings).should == 'Heya'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should translate a word in French" do
|
40
|
+
@c.request.env[:language] = 'fr'
|
41
|
+
@c.t(:greetings).should == 'Salut'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should translate passing the full locale" do
|
45
|
+
@c.t(:greetings, :language => 'en', :country => 'UK').should == 'Heya'
|
46
|
+
@c.t(:greetings, :language => 'en', :country => 'US').should == 'Howdie'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should translate passing the language" do
|
50
|
+
@c.t(:greetings, :language => 'fr').should == 'Salut'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should translate with domain" do
|
54
|
+
@c.t(:night, :greetings, :language => 'en').should == 'Good evening'
|
55
|
+
@c.t(:night, :greetings, :language => 'ja').should == 'こんばんわ'
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should localize date" do
|
59
|
+
date = Date.new(2009,1,1)
|
60
|
+
@c.t("%Y/%m/%d", date, :language => 'en').should == "2009/01/01"
|
61
|
+
@c.t("%Y/%{mon}/%{day}", date, :language => 'en').should == "2009/1/1"
|
62
|
+
@c.t("%a/%d", date, :language => 'en').should == "T/01"
|
63
|
+
@c.t("%a/%d", date, :language => 'en', :country => 'UK').should == "T/01"
|
64
|
+
@c.t("%a/%d", date, :language => 'ja').should == "木/01"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should localize time" do
|
68
|
+
time = Time.now
|
69
|
+
if time.hour < 12
|
70
|
+
@c.t("%p", time, :language => "ja").should == "午前"
|
71
|
+
else
|
72
|
+
@c.t("%p", time, :language => "ja").should == "午後"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/m_l10n_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "ML10n" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@lang_test_path = File.expand_path(File.dirname(__FILE__) + "/lang")
|
7
|
+
@lang_test_path_2 = File.expand_path(File.dirname(__FILE__) + "/other_lang_dir")
|
8
|
+
ML10n.reset_localization_files_and_dirs!
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:each) do
|
12
|
+
ML10n.reset_localizations!
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have a list of localization directories" do
|
16
|
+
ML10n.localization_dirs.should == Merb::Plugins.config[:merb_babel][:localization_dirs]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be able to add a new localization directory" do
|
20
|
+
ML10n.add_localization_dir(@lang_test_path)
|
21
|
+
ML10n.localization_dirs.include?(@lang_test_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should have a list of localization source files" do
|
25
|
+
ML10n.localization_files.should == []
|
26
|
+
ML10n.add_localization_dir(@lang_test_path)
|
27
|
+
ML10n.localization_files.include?("#{@lang_test_path}/en.yml").should be_true
|
28
|
+
ML10n.localization_files.include?("#{@lang_test_path}/en-US.yml").should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should load localization files and have them available" do
|
32
|
+
ML10n.add_localization_dir(@lang_test_path)
|
33
|
+
ML10n.load_localization!
|
34
|
+
ML10n.localizations['en']['right'].should == 'right'
|
35
|
+
ML10n.localizations['en']['left'].should == 'left'
|
36
|
+
ML10n.localizations['en']['US']['greetings'].should == 'Howdie'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should load more localization files and have them available" do
|
40
|
+
ML10n.add_localization_dir(@lang_test_path)
|
41
|
+
ML10n.load_localization!
|
42
|
+
ML10n.localizations['en']['right'].should == 'right'
|
43
|
+
ML10n.localizations.has_key?('fr').should be_false
|
44
|
+
|
45
|
+
ML10n.add_localization_dir(@lang_test_path_2)
|
46
|
+
ML10n.load_localization!
|
47
|
+
ML10n.localizations['en']['right'].should == 'right'
|
48
|
+
ML10n.localizations.has_key?('fr').should be_true
|
49
|
+
ML10n.localizations['fr']['right'].should == 'la droite'
|
50
|
+
ML10n.localizations['fr']['left'].should == 'la gauche'
|
51
|
+
ML10n.localizations['fr']['greetings'].should == 'Salut'
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe 'using set_locale before filter, ' do
|
5
|
+
describe 'a controller' do
|
6
|
+
|
7
|
+
describe 'locale' do
|
8
|
+
|
9
|
+
it "should be set by default" do
|
10
|
+
c = dispatch_to(TestController, :index)
|
11
|
+
c.locale.should == 'en-US'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be able to be set by passing a param" do
|
15
|
+
c = dispatch_to(TestController, :index, :locale => 'fr-FR')
|
16
|
+
c.locale.should == 'fr-FR'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be able to be set using the session" do
|
20
|
+
c = dispatch_to(TestController, :index) do |controller|
|
21
|
+
controller.stub!(:session).and_return( :locale => "es-BO" )
|
22
|
+
end
|
23
|
+
c.locale.should == 'es-BO'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be set using an url (when the routes are set properly)" do
|
27
|
+
#c = get('tests')
|
28
|
+
#c.locale.should == 'en-US'
|
29
|
+
c = get('en-US/tests')
|
30
|
+
c.locale.should == 'en-US'
|
31
|
+
c = get('en-UK/tests')
|
32
|
+
c.locale.should == 'en-UK'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should support longer locales (like zh-Hans-CN)" do
|
36
|
+
c = dispatch_to(TestController, :index, :locale => 'zh-Hans-CN')
|
37
|
+
c.locale.should == 'zh-hans-CN'
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'language' do
|
43
|
+
|
44
|
+
it "should be set by default" do
|
45
|
+
c = dispatch_to(TestController, :index)
|
46
|
+
c.language.should == 'en'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should be able to be set by passing a param" do
|
50
|
+
c = dispatch_to(TestController, :index, :language => 'fr')
|
51
|
+
c.language.should == 'fr'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should bet set when a locale was set by params" do
|
55
|
+
c = dispatch_to(TestController, :index, :locale => 'fr-FR')
|
56
|
+
c.locale.should == 'fr-FR'
|
57
|
+
c.language.should == 'fr'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be set when a locale was set by params even with a long locale" do
|
61
|
+
c = dispatch_to(TestController, :index, :locale => 'zh-Hans-CN')
|
62
|
+
c.language.should == 'zh-hans'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should bet set when a locale was set by session" do
|
66
|
+
c = dispatch_to(TestController, :index) do |controller|
|
67
|
+
controller.stub!(:session).and_return( :locale => "es-BO" )
|
68
|
+
end
|
69
|
+
c.language.should == 'es'
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should be set by the router" do
|
73
|
+
c = get('fr/languages')
|
74
|
+
c.language.should == 'fr'
|
75
|
+
c.locale.should == 'en-US'
|
76
|
+
# c = get('languages')
|
77
|
+
# c.language.should == 'en'
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'country' do
|
83
|
+
|
84
|
+
it "should be set by default" do
|
85
|
+
c = dispatch_to(TestController, :index)
|
86
|
+
c.country.should == 'US'
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should be able to be set by passing a param" do
|
90
|
+
c = dispatch_to(TestController, :index, :country => 'ES')
|
91
|
+
c.country.should == 'ES'
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should bet set when a locale was set by params" do
|
95
|
+
c = dispatch_to(TestController, :index, :locale => 'fr-FR')
|
96
|
+
c.country.should == 'FR'
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should bet set when a locale was set by session" do
|
100
|
+
c = dispatch_to(TestController, :index) do |controller|
|
101
|
+
controller.stub!(:session).and_return( :locale => "es-BO" )
|
102
|
+
end
|
103
|
+
c.country.should == 'BO'
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'using set_language, ' do
|
112
|
+
describe 'a controller' do
|
113
|
+
describe 'language' do
|
114
|
+
|
115
|
+
it "should be set by default" do
|
116
|
+
c = dispatch_to(LanguageController, :index)
|
117
|
+
c.language.should == 'en'
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should be able to be set by passing a param" do
|
121
|
+
c = dispatch_to(LanguageController, :index, :language => 'fr')
|
122
|
+
c.language.should == 'fr'
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#################################################
|
2
|
+
# French localization
|
3
|
+
#
|
4
|
+
# localization specific must go in their own file
|
5
|
+
# see en-US.yml for instance
|
6
|
+
#################################################
|
7
|
+
mloc_language_code: fr
|
8
|
+
# mloc_country:
|
9
|
+
#################################################
|
10
|
+
|
11
|
+
right: la droite
|
12
|
+
left: la gauche
|
13
|
+
greetings: Salut
|
14
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
$TESTING=true
|
2
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require "rubygems"
|
4
|
+
require "spec"
|
5
|
+
require "merb-core"
|
6
|
+
require File.join(File.dirname(__FILE__), "..", 'lib', 'merb_babel')
|
7
|
+
|
8
|
+
default_options = {
|
9
|
+
:environment => 'test',
|
10
|
+
:adapter => 'runner',
|
11
|
+
:session_store => 'cookie',
|
12
|
+
:session_secret_key => '187a66e27674660418cf4499471d5a0587f360d0'
|
13
|
+
}
|
14
|
+
|
15
|
+
options = default_options.merge($START_OPTIONS || {})
|
16
|
+
|
17
|
+
Merb.disable(:initfile)
|
18
|
+
Merb.start_environment(options)
|
19
|
+
|
20
|
+
Spec::Runner.configure do |config|
|
21
|
+
config.include Merb::Test::ViewHelper
|
22
|
+
config.include Merb::Test::RouteHelper
|
23
|
+
config.include Merb::Test::RequestHelper
|
24
|
+
config.include Merb::Test::ControllerHelper
|
25
|
+
end
|
26
|
+
|
27
|
+
Merb.load_dependencies(:environment => 'test')
|
28
|
+
|
29
|
+
Merb::Router.prepare do |r|
|
30
|
+
r.match(/\/?(en\-US|en\-UK|es\-ES|es\-AR)?/).to(:locale => "[1]") do |l|
|
31
|
+
l.match("/tests").to(:controller => "test_controller")
|
32
|
+
end
|
33
|
+
r.match(/\/?(en|es|fr|de)?/).to(:language => "[1]") do |l|
|
34
|
+
l.match("/languages").to(:controller => "language_controller")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
class TestController < Merb::Controller
|
41
|
+
|
42
|
+
before :set_locale
|
43
|
+
def index; end
|
44
|
+
end
|
45
|
+
|
46
|
+
class LanguageController < Merb::Controller
|
47
|
+
|
48
|
+
before :set_language
|
49
|
+
def index; end
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: merb_babel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Aimonetti
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-16 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: merb-core
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: locale
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.0
|
34
|
+
version:
|
35
|
+
description: Merb plugin that provides simple localization/internationalisation
|
36
|
+
email: mattaimonetti@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README.markdown
|
43
|
+
- LICENSE
|
44
|
+
- TODO
|
45
|
+
files:
|
46
|
+
- LICENSE
|
47
|
+
- README.markdown
|
48
|
+
- Rakefile
|
49
|
+
- TODO
|
50
|
+
- lib/merb_babel
|
51
|
+
- lib/merb_babel/locale_detector.rb
|
52
|
+
- lib/merb_babel/m_i18n.rb
|
53
|
+
- lib/merb_babel/m_l10n.rb
|
54
|
+
- lib/merb_babel/m_locale.rb
|
55
|
+
- lib/merb_babel/merbtasks.rb
|
56
|
+
- lib/merb_babel.rb
|
57
|
+
- spec/lang
|
58
|
+
- spec/lang/en-UK.yml
|
59
|
+
- spec/lang/en-US.yml
|
60
|
+
- spec/lang/en.yml
|
61
|
+
- spec/lang/ja.yml
|
62
|
+
- spec/locale_detector_spec.rb
|
63
|
+
- spec/m_i18n_spec.rb
|
64
|
+
- spec/m_l10n_spec.rb
|
65
|
+
- spec/merb_babel_spec.rb
|
66
|
+
- spec/other_lang_dir
|
67
|
+
- spec/other_lang_dir/fr.yml
|
68
|
+
- spec/spec_helper.rb
|
69
|
+
has_rdoc: true
|
70
|
+
homepage: http://github.com/mattetti/merb_babel/
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "0"
|
81
|
+
version:
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: "0"
|
87
|
+
version:
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project: merb
|
91
|
+
rubygems_version: 1.3.1
|
92
|
+
signing_key:
|
93
|
+
specification_version: 2
|
94
|
+
summary: Merb plugin that provides simple localization/internationalisation
|
95
|
+
test_files: []
|
96
|
+
|