Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial import

  • Loading branch information...
commit 3ffc05228931f99acedc932d46c1ef84e1558d02 0 parents
PerfectLine authored
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 PerfectLine LLC (www.perfectline.co.uk)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
70 README.rdoc
@@ -0,0 +1,70 @@
+=== LocaleRouting
+
+LocaleRouting makes parsing I18N locale from an url parameter seamless.
+It taps into the route recognition and generation methods and checks
+or adds the locale when nessecary.
+
+The plugin loads its available locales from Rails default I18N class.
+For every request, it checks if the firs 2 characters of the parameters part in the
+URL match any of the locale definitions exposed by I18n.available_locales.
+IF a locale string is found, the application I18n.locale is changed and the locale is passed
+via params[:locale].
+
+Access to mapped URLs is wrapped also, the current I18n.locale is always
+prepended to the generated URLs parameters. Additionally you can pass a
+{:locale => "en} option to your link helpers, which will inject the given
+locale into the output URL. This parameter defaults to I18n.locale.
+
+No routes have to be changed to use this functionality.
+
+=== Configuration
+
+To enable or disable the locale routing
+Perfectline::LocaleRouting.enabled = true/false # defaults to true
+
+To specifiy which part of the URL should be matched for the locale identifier
+Perfectline::LocaleRouting.match_from = option
+
+Available options for match_from are:
+* :params
+ Searches for a 2 letter locale string in the parameters, specifically in the first query stirng token.
+ Found token is matched against I18n.available_locales and if no such locale exists, it will fall back to the default locale.
+ Example: www.myhost.com/en/foo/bar
+
+Example:
+ www.myapp.com resolves to root controller with the default locale
+ www.myapp.com/en resolves to root controller with locale => "en"
+ www.myapp.com/foo/bar resolves to "foo" controller, "bar" action with default locale
+ www.myapp.com/fr/foo/bar resolves to "foo" controller, "bar" action with locale => "fr"
+
+* :host
+ Searches for configured matches in the domain name. If a match is found, the configured locale is then checked against I18n.available_locales.
+ If the configured locale does not exist in available locales, it will fall back to the default locale.
+
+Configuring host to locale mappings is done via Perfectline::LocaleRouting.create_mapping = hash.
+Hash key must be the hostname pattern to be matched and value is the locale string.
+Hostname patterns are like simplified regexp patterns with * wildcard support.
+Mappings matching is similar to route config - first match found is used, rest is ignored.
+
+Example:
+ Perfectline::LocaleRouting.create_mapping({
+ "en.dev.*" => "en", # matches en.dev.yoursite.com and en.dev.mysite.co.uk
+ "*.dev.*" => "en", # matches foo.dev.yoursite.com and www.dev.yoursite.com but not en.dev.mysite.com as its defined AFTER that mapping
+ "en.*" => "en", # matches en.yoursite.com but not en.dev.yoursite.com or en.foo.dev.yoursite.com as its defined AFTER that mapping
+ "*.com" => "en", # matches anything with a .com TLD
+ })
+
+=== Warning
+This plugin has not been fully tested with all possible cases except perhaps the params locale matching.
+As you can see there are no tests yet either, although they will be created as soon as possible.
+So if you do run into issues or have any improvement ideas, feel free to contact the authors.
+
+=== Honorable mentions
+This plugin is heavily inspired by the "routing-filter" plugin by Sven Fuchs.
+
+=== Authors:
+Tanel Suurhans - tanel.suurhans__at__perfectline__d0t__ee
+Tarmo Lehtpuu - tarmo.lehtpuu__at__perfectline__d0t_ee
+
+== License
+Copyright 2009 by PerfectLine LLC (www.perfectline.co.uk) and is released under the MIT license.
23 Rakefile
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the LocaleRouting plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the LocaleRouting plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'LocaleRouting'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
1  init.rb
@@ -0,0 +1 @@
+require 'locale_routing'
2  install.rb
@@ -0,0 +1,2 @@
+# spit out README
+puts IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
7 lib/locale_routing.rb
@@ -0,0 +1,7 @@
+require 'i18n'
+require 'locale_routing/config'
+require 'locale_routing/locale_route_set'
+require 'locale_routing/locale'
+
+# wire up routing hooks
+Perfectline::LocaleRouting.bootstrap
54 lib/locale_routing/config.rb
@@ -0,0 +1,54 @@
+module Perfectline
+ module LocaleRouting
+
+ @locale_match_options = [:params, :host]
+ @host_mapping = []
+
+ # defaults
+ @enabled = true
+ @match_from = :params
+
+ class << self
+
+ def enabled?
+ @enabled
+ end
+
+ def enabled=(enabled)
+ @enabled = (enabled.nil? || enabled == false) ? false : true
+ end
+
+ def match_from
+ @match_from
+ end
+
+ def match_from=(location)
+ unless @locale_match_options.include?(location.to_sym)
+ raise "#{location.to_sym} is not supported as Perfectline::LocaleRouting.match_from option."
+ end
+
+ @match_from = location.to_sym
+ end
+
+ def host_mapping
+ @host_mapping
+ end
+
+ def create_mapping(hash)
+ unless hash.kind_of?(Hash)
+ raise "Supplied parameter for Perfectline::LocaleRouting.domain_mapping must be a Hash"
+ end
+
+ hash.each do |host, locale|
+ @host_mapping.push({:host => host.to_s.gsub('.', '\.').gsub('*', '.*'), :locale => locale.to_s})
+ end
+ end
+
+ # straps the LocaleRouteSet module into ActionControllers RouteSet
+ def bootstrap
+ ActionController::Routing::RouteSet.send(:include, Perfectline::LocaleRouting::LocaleRouteSet) if self.enabled?
+ end
+
+ end
+ end
+end
80 lib/locale_routing/locale.rb
@@ -0,0 +1,80 @@
+module Perfectline
+ module LocaleRouting
+ # class containing Locale handling methods
+ class Locale
+ class << self
+
+ # locale matching pattern
+ def match_params_locale
+ @@match_params_locale ||= %r(^/((#{I18n.available_locales.map{|o| Regexp.escape(o.to_s)}.join('|')})(?=/|$)))
+ end
+
+ def match_url
+ @@match_url ||= %r(^(http.?://[^/]*)?(.*))
+ end
+
+ # prepend locale to generated url
+
+ def prepend(result, locale)
+ # check the results
+ url = result.is_a?(Array) ? result.first : result
+ locale = I18n.locale if locale.nil?
+
+ # substitute the locale
+ url.sub!(self.match_url){"#{$1}/#{locale}#{$2}"}
+ end
+
+ # extract and set locale
+ def extract(path, env)
+ case Perfectline::LocaleRouting.match_from
+ when :params then path = extract_from_params(path)
+ when :host then extract_from_host(env)
+ end
+
+ return path
+ end
+
+ def extract_from_params(path)
+ # match for configured locales and remove them
+ replacement = path.sub!(self.match_params_locale, '')
+ locale = I18n.default_locale
+
+ # if matches were found, set the locale and new path
+ if (not replacement.nil?)
+ path = replacement
+ locale = $1.to_sym
+ else
+ RAILS_DEFAULT_LOGGER.info "No valid locale string found in the URL, falling back to #{locale}"
+ end
+
+ # set the locale and return the 'cleaned' path string
+ I18n.locale = locale and return path
+ end
+
+ def extract_from_host(env)
+ if env[:host].nil?
+ raise "Valid host not found (Perfectline::LocaleRouting.match_from = :host)."
+ end
+
+ host = env[:host].to_s
+ locale = I18n.default_locale
+ mappings = Perfectline::LocaleRouting.host_mapping
+
+ if mappings.nil? || mappings.empty?
+ RAILS_DEFAULT_LOGGER.warn "Perfectline::LocaleRouting.host_mapping is nil or empty."
+ end
+
+ puts mappings.inspect
+
+ mappings.each do |element|
+ unless host.match(%r(^#{element[:host]}$)).nil?
+ locale = element[:locale] and break
+ end
+ end
+
+ I18n.locale = locale
+ end
+ end
+ end
+ end
+end
48 lib/locale_routing/locale_route_set.rb
@@ -0,0 +1,48 @@
+module Perfectline
+ module LocaleRouting
+ # module containing methods for RouteSet extending
+ module LocaleRouteSet
+
+ def self.included(base)
+ base.send(:include, InstanceMethods)
+ base.alias_method_chain(:recognize_path, :locale)
+ base.alias_method_chain(:generate, :locale)
+ base.alias_method_chain(:extract_request_environment, :locale)
+ end
+
+ module InstanceMethods
+
+ # TODO: support locale in subdomain and top level domain extension
+ def recognize_path_with_locale(path, env)
+ # set locale and strip it from the path for recognition
+ path = Perfectline::LocaleRouting::Locale.extract(path, env)
+ # process the route and add the locale parameter to return value
+ returning recognize_path_without_locale(path, env) do |params|
+ params[:locale] = I18n.locale
+ end
+ end
+
+ def generate_with_locale(*args)
+ # check if locale is set
+ locale = args.first.delete(:locale)
+
+ returning generate_without_locale(*args) do |result|
+ Perfectline::LocaleRouting::Locale.prepend(result, locale)
+ end
+ end
+
+ # override request env extraction to include more info
+ def extract_request_environment_with_locale(request)
+ # merge the original hash with new info
+ extract_request_environment_without_locale(request).merge({
+ :host => request.host,
+ :port => request.port,
+ :domain => request.domain,
+ :subdomain => request.subdomains.first,
+ :subdomains => request.subdomains
+ })
+ end
+ end
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.