class Utopia::Localization
A middleware which attempts to find localized content.
Constants
- CURRENT_LOCALE_KEY
- HTTP_ACCEPT_LANGUAGE
- LOCALIZATION_KEY
- RESOURCE_NOT_FOUND
Attributes
all_locales[R]
default_locale[R]
Public Class Methods
[](request)
click to toggle source
# File lib/utopia/localization.rb, line 62 def self.[] request Wrapper.new(request.env) end
new(app, locales:, default_locale: nil, default_locales: nil, hosts: {}, ignore: [])
click to toggle source
@param locales [Array<String>] An array of all supported locales. @param default_locale
[String] The default locale if none is provided. @param default_locales [String] The locales to try in order if none is provided. @param hosts [Hash<Pattern, String>] Specify a mapping of the HTTP_HOST header to a given locale. @param ignore [Array<Pattern>] A list of patterns matched against PATH_INFO which will not be localized.
# File lib/utopia/localization.rb, line 77 def initialize(app, locales:, default_locale: nil, default_locales: nil, hosts: {}, ignore: []) @app = app @all_locales = HTTP::Accept::Languages::Locales.new(locales) # Locales here are represented as an array of strings, e.g. ['en', 'ja', 'cn', 'de'] and are used in order if no locale is specified by the user. unless @default_locales = default_locales if default_locale @default_locales = [default_locale, nil] else # We append nil, i.e. no localization. @default_locales = @all_locales.names + [nil] end end @default_locale = default_locale || @default_locales.first unless @default_locales.include? @default_locale @default_locales.unshift(@default_locale) end # Select a localization based on a request host name: @hosts = hosts @ignore = ignore || options[:nonlocalized] @methods = methods end
Public Instance Methods
browser_preferred_locales(env)
click to toggle source
# File lib/utopia/localization.rb, line 167 def browser_preferred_locales(env) accept_languages = env[HTTP_ACCEPT_LANGUAGE] # No user prefered languages: return [] unless accept_languages # Extract the ordered list of languages: languages = HTTP::Accept::Languages.parse(accept_languages) # Returns available languages based on the order languages: return @all_locales & languages rescue HTTP::Accept::ParseError # If we fail to parse the browser Accept-Language header, we ignore it (silently). return [] end
call(env)
click to toggle source
# File lib/utopia/localization.rb, line 207 def call(env) # Pass the request through if it shouldn't be localized: return @app.call(env) unless localized?(env) env[LOCALIZATION_KEY] = self response = nil # We have a non-localized request, but there might be a localized resource. We return the best localization possible: preferred_locales(env) do |localized_env| # puts "Trying locale: #{localized_env[CURRENT_LOCALE_KEY]}: #{localized_env[Rack::PATH_INFO]}..." response = @app.call(localized_env) break unless response[0] >= 400 end return vary(env, response) end
freeze()
click to toggle source
Calls superclass method
# File lib/utopia/localization.rb, line 106 def freeze return self if frozen? @all_locales.freeze @default_locales.freeze @default_locale.freeze @hosts.freeze @ignore.freeze super end
host_preferred_locales(env) { |locale| ... }
click to toggle source
# File lib/utopia/localization.rb, line 147 def host_preferred_locales(env) http_host = env[Rack::HTTP_HOST] # Yield all hosts which match the incoming http_host: @hosts.each do |pattern, locale| yield locale if http_host[pattern] end end
localized?(env)
click to toggle source
# File lib/utopia/localization.rb, line 183 def localized?(env) # Ignore requests which match the ignored paths: path_info = env[Rack::PATH_INFO] return false if @ignore.any? { |pattern| path_info[pattern] != nil } return true end
preferred_locales(env) { |merge(CURRENT_LOCALE_KEY => locale)| ... }
click to toggle source
# File lib/utopia/localization.rb, line 121 def preferred_locales(env) return to_enum(:preferred_locales, env) unless block_given? # Keep track of what locales have been tried: locales = Set.new host_preferred_locales(env) do |locale| yield env.merge(CURRENT_LOCALE_KEY => locale) if locales.add? locale end request_preferred_locale(env) do |locale, path| # We have extracted a locale from the path, so from this point on we should use the updated path: env = env.merge(Rack::PATH_INFO => path.to_s) yield env.merge(CURRENT_LOCALE_KEY => locale) if locales.add? locale end browser_preferred_locales(env).each do |locale| yield env.merge(CURRENT_LOCALE_KEY => locale) if locales.add? locale end @default_locales.each do |locale| yield env.merge(CURRENT_LOCALE_KEY => locale) if locales.add? locale end end
request_preferred_locale(env) { |request_locale, path| ... }
click to toggle source
# File lib/utopia/localization.rb, line 156 def request_preferred_locale(env) path = Path[env[Rack::PATH_INFO]] if request_locale = @all_locales.patterns[path.first] # Remove the localization prefix: path.delete_at(0) yield request_locale, path end end
vary(env, response)
click to toggle source
Set the Vary: header on the response to indicate that this response should include the header in the cache key.
# File lib/utopia/localization.rb, line 192 def vary(env, response) headers = response[1].to_a # This response was based on the Accept-Language header: headers << ['Vary', 'Accept-Language'] # Althought this header is generally not supported, we supply it anyway as it is useful for debugging: if locale = env[CURRENT_LOCALE_KEY] # Set the Content-Location to point to the localized URI as requested: headers['Content-Location'] = "/#{locale}" + env[Rack::PATH_INFO] end return response end