class Middleman::CoreExtensions::Internationalization

Public Class Methods

new(app, options_hash={}, &block) click to toggle source
Calls superclass method Middleman::Extension::new
# File lib/middleman-more/core_extensions/i18n.rb, line 10
def initialize(app, options_hash={}, &block)
  super

  # TODO
  # If :directory_indexes is already active,
  # throw a warning explaining the bug and telling the use
  # to reverse the order.

  # See https://github.com/svenfuchs/i18n/wiki/Fallbacks
  unless options[:no_fallbacks]
    require 'i18n/backend/fallbacks'
    ::I18n::Backend::Simple.send(:include, ::I18n::Backend::Fallbacks)
  end

  app.config.define_setting :locales_dir, 'locales', 'The directory holding your locale configurations'

  app.send :include, LocaleHelpers
end

Public Instance Methods

after_configuration() click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 29
def after_configuration
  app.files.reload_path(app.config[:locals_dir] || options[:data])

  @locales_glob = File.join(app.config[:locals_dir] || options[:data], '**', '*.{rb,yml,yaml}')
  @locales_regex = convert_glob_to_regex(@locales_glob)

  @maps = {}
  @mount_at_root = options[:mount_at_root].nil? ? langs.first : options[:mount_at_root]

  configure_i18n

  unless app.build?
    logger.info "== Locales: #{langs.join(', ')} (Default #{@mount_at_root})"
  end

  # Don't output localizable files
  app.ignore File.join(options[:templates_dir], '**')

  app.sitemap.provides_metadata_for_path(&method(:metadata_for_path))
  app.files.changed(&method(:on_file_changed))
  app.files.deleted(&method(:on_file_changed))
end
langs() click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 60
def langs
  @_langs ||= known_languages
end
manipulate_resource_list(resources) click to toggle source

Update the main sitemap resource list @return [void]

# File lib/middleman-more/core_extensions/i18n.rb, line 66
def manipulate_resource_list(resources)
  @_localization_data = {}

  new_resources = []

  resources.each do |resource|
    # If it uses file extension localization
    if parse_locale_extension(resource.path)
      result = parse_locale_extension(resource.path)
      ext_lang, path, page_id = result
      new_resources << build_resource(path, resource.path, page_id, ext_lang)
    # If it's a "localizable template"
    elsif File.fnmatch?(File.join(options[:templates_dir], '**'), resource.path)
      page_id = File.basename(resource.path, File.extname(resource.path))
      langs.each do |lang|
        # Remove folder name
        path = resource.path.sub(options[:templates_dir], '')
        new_resources << build_resource(path, resource.path, page_id, lang)
      end
    end
  end

  resources + new_resources
end
t(*args) click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 53
def t(*args)
  ::I18n.t(*args)
end

Private Instance Methods

build_resource(path, source_path, page_id, lang) click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 176
def build_resource(path, source_path, page_id, lang)
  old_locale = ::I18n.locale
  ::I18n.locale = lang
  localized_page_id = ::I18n.t("paths.#{page_id}", default: page_id, fallback: [])

  prefix = if (options[:mount_at_root] == lang) || (options[:mount_at_root].nil? && langs[0] == lang)
    '/'
  else
    replacement = options[:lang_map].fetch(lang, lang)
    options[:path].sub(':locale', replacement.to_s)
  end

  # path needs to be changed if file has a localizable extension. (options[mount_at_root] == lang)
  path = ::Middleman::Util.normalize_path(
    File.join(prefix, path.sub(page_id, localized_page_id))
  )

  path.gsub!(options[:templates_dir] + '/', '')

  @_localization_data[path] = [lang, path, localized_page_id]

  p = ::Middleman::Sitemap::Resource.new(app.sitemap, path)
  p.proxy_to(source_path)

  ::I18n.locale = old_locale
  p
end
configure_i18n() click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 106
def configure_i18n
  ::I18n.load_path += Dir[File.join(app.root, @locales_glob)]
  ::I18n.reload!

  ::I18n.default_locale = @mount_at_root

  # Reset fallbacks to fall back to our new default
  ::I18n.fallbacks = ::I18n::Locale::Fallbacks.new if ::I18n.respond_to?(:fallbacks)
end
convert_glob_to_regex(glob) click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 100
def convert_glob_to_regex(glob)
  # File.fnmatch doesn't support brackets: {rb,yml,yaml}
  regex = glob.sub(/\./, '\.').sub(File.join('**', '*'), '.*').sub(/\//, '\/').sub('{rb,yml,yaml}', '(rb|ya?ml)')
  %r{^#{regex}}
end
known_languages() click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 142
def known_languages
  if options[:langs]
    Array(options[:langs]).map(&:to_sym)
  else
    known_langs = app.files.known_paths.select do |p|
      p.to_s.match(@locales_regex) && (p.to_s.split(File::SEPARATOR).length == 2)
    end

    known_langs.map { |p|
      File.basename(p.to_s).sub(/\.ya?ml$/, '').sub(/\.rb$/, '')
    }.sort.map(&:to_sym)
  end
end
localization_data(path) click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 156
def localization_data(path)
  @_localization_data ||= {}
  @_localization_data[path]
end
metadata_for_path(url) click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 116
def metadata_for_path(url)
  if d = localization_data(url)
    lang, page_id = d
  else
    # Default to the @mount_at_root lang
    page_id = nil
    lang = @mount_at_root
  end

  instance_vars = proc do
    @lang         = lang
    @page_id      = page_id
  end

  locals = {
    lang: lang,
    page_id: page_id
  }

  {
    blocks: [instance_vars],
    locals: locals,
    options: { lang: lang }
  }
end
on_file_changed(file) click to toggle source
# File lib/middleman-more/core_extensions/i18n.rb, line 93
def on_file_changed(file)
  return unless @locales_regex =~ file

  @_langs = nil # Clear langs cache
  ::I18n.reload!
end
parse_locale_extension(path) click to toggle source

Parse locale extension filename @return [lang, path, basename] will return nil if no locale extension

# File lib/middleman-more/core_extensions/i18n.rb, line 164
def parse_locale_extension(path)
  path_bits = path.split('.')
  return nil if path_bits.size < 3

  lang = path_bits.delete_at(-2).to_sym
  return nil unless langs.include?(lang)

  path = path_bits.join('.')
  basename = File.basename(path_bits[0..-2].join('.'))
  [lang, path, basename]
end