merb_babel 0.1.2
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/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
|
+
|