module R18n::Filters

Filter is a way, to process translations: escape HTML entries, convert from Markdown syntax, etc.

In translation file filtered content must be marked by YAML type:

filtered: !!custom_type
  This content will be processed by filter

Filter function will be receive filtered content as first argument, struct with filter config as second and filter parameters as next arguments. You can set passive filter, which will process translation only on loading.

R18n::Filters.add('custom_type', :no_space) do |content, config, replace|
  content.gsub(' ', replace)
end
R18n::Filters.add('custom_type', passive: true) do |content, config|
  content + '!'
end

i18n.filtered('_') #=> "This_content_will_be_processed_by_filter!"

Use `String` class as type to add global filter for all translated strings:

R18n::Filters.add(String, :escape_html) do |content, config, params|
  escape_html(content)
end

Filter config contain two parameters: translation locale and path. But it is `Hash` and you can add you own parameter to cross-filter communications:

R18n::Filters.add(String, :hide_truth) do |content, config|
  return content if config[:censorship_check]

  if content.scan(CENSORSHIP_WORDS[config[:locale]]).empty?
    content
  else
    "Error in #{config[:path]}"
  end
end

R18n::Filters.add('passed', :show_lie) do |content, config|
  config[:censorship_check] = true
  content
end

You can disable, enabled and delete filters:

R18n::Filters.off(:no_space))
i18n.filtered('_') #=> "This content will be processed by filter!"
R18n::Filters.on(:no_space)
i18n.filtered('_') #=> "This_content_will_be_processed_by_filter!"
R18n::Filters.delete(:no_space)

You can enabled/disabled filters only for special `I18n` object:

R18n::I18n.new('en', nil, on_filters: [:untranslated_html, :no_space],
                          off_filters: :untranslated )

Constants

Filter

Attributes

active_enabled[RW]

`Hash` of types to enabled active filters.

by_type[RW]

`Hash` of types to all Filters.

defined[RW]

`Hash` of filter names to Filters.

enabled[RW]

`Hash` of types to enabled passive and active filters.

passive_enabled[RW]

`Hash` of types to enabled passive filters.

Public Class Methods

add(types, name = nil, options = {}, &block) click to toggle source

Add new filter for `type` with `name` and return filter object. You can use `String` class as `type` to add global filter for all translated string.

Filter content will be sent to `block` as first argument, struct with config as second and filters parameters will be in next arguments.

Options:

  • `position` – change order on processing several filters for same type.

    Note that passive filters will be always run before active.
  • `passive` – if `true`, filter will process only on translation loading. Note that you must add all passive before load translation.

# File lib/r18n-core/filters.rb, line 128
def add(types, name = nil, options = {}, &block)
  if name.is_a? Hash
    options = name
    name = nil
  end
  types = Array(types)

  if name
    delete(name)
  else
    @last_auto_name ||= 0
    loop do
      @last_auto_name += 1
      name = @last_auto_name
      break unless defined.key? name
    end
  end

  filter = Filter.new(name, types, block, true, options[:passive])
  @defined[name] = filter

  types.each do |type|
    @by_type[type] = [] unless @by_type.key? type
    if options.key? :position
      @by_type[type].insert(options[:position], filter)
    else
      @by_type[type] << filter
    end
    rebuild_enabled! type
  end

  if defined?(@new_filter_listener) && @new_filter_listener.is_a?(Proc)
    @new_filter_listener.call(filter)
  end
  filter
end
delete(filter) click to toggle source

Delete `filter` by name or Filter object.

# File lib/r18n-core/filters.rb, line 166
def delete(filter)
  filter = @defined[filter] unless filter.is_a? Filter
  return unless filter

  @defined.delete(filter.name)
  filter.types.each do |type|
    @by_type[type].delete(filter)
    rebuild_enabled! type
  end
end
listen() { || ... } click to toggle source

Return filters, which be added inside `block`.

# File lib/r18n-core/filters.rb, line 196
def listen(&_block)
  filters = []
  @new_filter_listener = proc { |i| filters << i }
  yield
  @new_filter_listener = nil
  filters
end
off(filter) click to toggle source

Disable `filter` by name or Filter object.

# File lib/r18n-core/filters.rb, line 178
def off(filter)
  filter = @defined[filter] unless filter.is_a? Filter
  return unless filter

  filter.enabled = false
  filter.types.each { |type| rebuild_enabled! type }
end
on(filter) click to toggle source

Turn on disabled `filter` by name or Filter object.

# File lib/r18n-core/filters.rb, line 187
def on(filter)
  filter = @defined[filter] unless filter.is_a? Filter
  return unless filter

  filter.enabled = true
  filter.types.each { |type| rebuild_enabled! type }
end
rebuild_enabled!(type) click to toggle source

Rebuild `active_enabled` and `passive_enabled` for `type`.

# File lib/r18n-core/filters.rb, line 99
def rebuild_enabled!(type)
  @passive_enabled[type] = []
  @active_enabled[type] = []
  @enabled[type] = []

  @by_type[type].each do |filter|
    next unless filter.enabled?

    @enabled[type] << filter
    if filter.passive?
      @passive_enabled[type] << filter
    else
      @active_enabled[type] << filter
    end
  end
end