module RailsTranslateRoutes::Translator

Public Instance Methods

add_prefix?(locale) click to toggle source

Add prefix for all non-default locales

# File lib/rails-translate-routes.rb, line 345
def add_prefix? locale
  if @no_prefixes
    false
  elsif !default_locale?(locale) || @prefix_on_default_locale
    true
  else
    false
  end
end
add_root_route(root_route, route_set) click to toggle source

Add unmodified root route to route_set

# File lib/rails-translate-routes.rb, line 242
def add_root_route root_route, route_set
  if @prefix_on_default_locale
    if Rails.version >= '3.2'
      conditions = { :path_info => root_route.path.spec.to_s }
      conditions[:request_method] = parse_request_methods root_route.verb if root_route.verb != //
      route_set.add_route root_route.app, conditions, root_route.requirements, root_route.defaults, root_route.name
    else
      root_route.conditions[:path_info] = root_route.conditions[:path_info].dup
      route_set.set.add_route *root_route
      route_set.named_routes[root_route.name] = root_route
      route_set.routes << root_route
    end
  end
end
add_untranslated_helpers_to_controllers_and_views(old_name) click to toggle source

Add standard route helpers for default locale e.g.

I18n.locale = :de
people_path -> people_de_path
I18n.locale = :fr
people_path -> people_fr_path
# File lib/rails-translate-routes.rb, line 262
def add_untranslated_helpers_to_controllers_and_views old_name
  ['path', 'url'].map do |suffix|
    new_helper_name = "#{old_name}_#{suffix}"

    ROUTE_HELPER_CONTAINER.each do |helper_container|
      helper_container.send :define_method, new_helper_name do |*args|
        send "#{old_name}_#{locale_suffix(args.select{|arg| arg.is_a?(Hash)}.first.try(:[], :locale) || I18n.locale)}_#{suffix}", *args
      end

      # !!! very dirty hack to ensure it works inside Engines
      #
      # helper_container.send :define_method, :method_missing do |*args|
      #   metod = args.shift
      #   if metod[/_path/] || metod[/_url/] and self.class != helper_container and !metod[/\w{2}(_path|_url)/]
      #     self.class.send :define_method, metod do |*arguments|
      #       locale = arguments.select{|arg| arg.is_a?(Hash)}.first.try(:[], :locale)
      #       send metod.to_s.gsub(/path$/, "#{locale || I18n.locale}_path").gsub(/url$/, "#{locale || I18n.locale}_url"), *arguments
      #     end
      #     send *args.unshift(metod)
      #   else
      #     super *args.unshift(metod)
      #   end
      # end
    end

    new_helper_name.to_sym
  end
end
split_translate_join(segment, locale, separators, translate = true) click to toggle source
# File lib/rails-translate-routes.rb, line 364
def split_translate_join(segment, locale, separators, translate = true)
  separator = separators[0]
  final_optional_segments = segment[Regexp.new("(#{'\\' + separator })$")] || ""
  segment.split(separator).map do |s|
    if separators[1..-1].any?
      split_translate_join(s, locale, separators[1..-1], translate)
    else
      translate ? translate_path_segment(s,locale) : s
    end
  end.join(separator) + (final_optional_segments != "/" ? final_optional_segments : '')
end
translate(route_set) click to toggle source

Translate a specific RouteSet, usually Rails.application.routes, but can be a RouteSet of a gem, plugin/engine etc.

# File lib/rails-translate-routes.rb, line 193
def translate route_set
  route_set ||= custom_route_set
  Rails.logger.info "Translating routes (default locale: #{default_locale})" if defined?(Rails) && defined?(Rails.logger)

  # save original routes and clear route set
  original_routes = route_set.routes.dup                     # Array [routeA, routeB, ...]

  if Rails.version >= '3.2'
    original_routes.routes.delete_if{|r| r.path.spec.to_s == '/assets'  }
  else
    original_routes.delete_if{|r| r.path == '/assets'}
  end

  original_named_routes = route_set.named_routes.routes.dup  # Hash {:name => :route}

  if Rails.version >= '3.2'
    translated_routes = []
    original_routes.each do |original_route|
      translations_for(original_route).each do |translated_route_args|
        translated_routes << translated_route_args
      end
    end

    reset_route_set route_set

    translated_routes.each do |translated_route_args|
      route_set.add_route *translated_route_args
    end
  else
    reset_route_set route_set

    original_routes.each do |original_route|
      translations_for(original_route).each do |translated_route_args|
        route_set.add_route *translated_route_args
      end
    end
  end

  original_named_routes.each_key do |route_name|
    route_set.named_routes.helpers.concat add_untranslated_helpers_to_controllers_and_views(route_name)
  end

  if root_route = original_named_routes[:root]
    add_root_route root_route, route_set
  end

end
translate_path(path, locale) click to toggle source

Translates a path and adds the locale prefix.

# File lib/rails-translate-routes.rb, line 356
def translate_path path, locale
  new_path = split_translate_join path, locale, [')','(','/'], false
  new_path = split_translate_join path, locale, [')','(','/']
  new_path = "/:locale#{new_path || '/'}" if add_prefix?(locale)
  new_path = '/' if new_path.blank?
  new_path
end
translate_path_segment(segment, locale) click to toggle source

Tries to translate a single path segment. If the path segment contains sth. like an optional format “people(.:format)”, only “people” will be translated, if there is no translation, the path segment is blank or begins with a “:” (param key), the segment is returned untouched

# File lib/rails-translate-routes.rb, line 381
def translate_path_segment segment, locale
  return segment if segment.blank? or segment.starts_with?(":")

  match = TRANSLATABLE_SEGMENT.match(segment)[1] rescue nil

  (translate_string(match, locale) || segment)
end
translate_route(route, locale) click to toggle source

Generate translation for a single route for one locale

# File lib/rails-translate-routes.rb, line 304
def translate_route route, locale
  locale = locale.to_s
  if Rails.version >= '3.2'
    conditions = { :path_info => translate_path(route.path.spec.to_s, locale) }
    conditions[:request_method] = parse_request_methods route.verb if route.verb != //
    if route.constraints
      route.constraints.each do |k,v|
        conditions[k] = v unless k == :request_method
      end
    end
    defaults = route.defaults.merge LOCALE_PARAM_KEY => locale.dup
  else
    conditions = { :path_info => translate_path(route.path, locale) }
    conditions[:request_method] = parse_request_methods route.conditions[:request_method] if route.conditions.has_key? :request_method
    defaults = route.defaults.merge LOCALE_PARAM_KEY => locale
  end

  requirements = route.requirements.merge LOCALE_PARAM_KEY => locale
  new_name = "#{route.name}_#{locale_suffix(locale)}" if route.name

  [route.app, conditions, requirements, defaults, new_name]
end
translate_string(str, locale) click to toggle source
# File lib/rails-translate-routes.rb, line 389
def translate_string str, locale
  @dictionary[locale.to_s][str.to_s]
end
translations_for(route) click to toggle source

Generate translations for a single route for all available locales

# File lib/rails-translate-routes.rb, line 292
def translations_for route
  translated_routes = []
  available_locales.map do |locale|
    translated_routes << translate_route(route, locale)
  end

  # add untranslated_route without url helper if we want to keep untranslated routes
  translated_routes << untranslated_route(route) if @keep_untranslated_routes
  translated_routes
end
untranslated_route(route) click to toggle source

Re-generate untranslated routes (original routes) with name set to nil (which prevents conflict with default untranslated_urls)

# File lib/rails-translate-routes.rb, line 328
def untranslated_route route
  conditions = {}
  if Rails.version >= '3.2'
    conditions[:path_info] = route.path.spec.to_s
    conditions[:request_method] = parse_request_methods route.verb if route.verb != //
    conditions[:subdomain] = route.constraints[:subdomain] if route.constraints
  else
    conditions[:path_info] = route.path
    conditions[:request_method] = parse_request_methods route.conditions[:request_method] if route.conditions.has_key? :request_method
  end
  requirements = route.requirements
  defaults = route.defaults

  [route.app, conditions, requirements, defaults]
end

Private Instance Methods

parse_request_methods(methods_regexp) click to toggle source

expects methods regexp to be in a format: /^GET$/ or /^GET|POST$/ and returns array [“GET”, “POST”]

# File lib/rails-translate-routes.rb, line 406
def parse_request_methods methods_regexp
  methods_regexp.source.gsub(/\^([a-zA-Z\|]+)\$/, "\\1").split("|")
end
remove_all_methods_in(mod) click to toggle source
# File lib/rails-translate-routes.rb, line 399
def remove_all_methods_in mod
  mod.instance_methods.each do |method|
    mod.send :remove_method, method
  end
end
reset_route_set(route_set) click to toggle source
# File lib/rails-translate-routes.rb, line 394
def reset_route_set route_set
  route_set.clear!
  remove_all_methods_in route_set.named_routes.module
end