module AnnoTranslate

Extentions to make internationalization (i18n) of a Rails application simpler. Support the method translate (or shorter t) in models/view/controllers/mailers.

Constants

VERSION

Public Class Methods

fallback(enable = true) click to toggle source

When fallback mode is enabled if a key cannot be found in the set locale, it uses the default locale. So, for example, if an app is mostly localized to Spanish (:es), but a new page is added then Spanish users will continue to see mostly Spanish content but the English version (assuming the default_locale is :en) for the new page that has not yet been translated to Spanish.

# File lib/annotranslate.rb, line 169
def self.fallback(enable = true)
  @@fallback_mode = enable
end
fallback?() click to toggle source

If fallback mode is enabled

# File lib/annotranslate.rb, line 174
def self.fallback?
  @@fallback_mode
end
log() click to toggle source

Plugin-specific Rails logger

# File lib/annotranslate.rb, line 38
def self.log
  # Create logger if it doesn't exist yet
  if @@logger.nil?
    log_file = Rails.root.join('log', 'annotranslate.log').to_s
    puts "AnnoTranslate is logging to: #{log_file}"
    @@logger = Logger.new(File.open(log_file, "w", encoding: 'UTF-8'))
    @@logger.info "Started new AnnoTranslate logging session!"
  end
  # Return the logger instance
  @@logger
end
pseudo_append() click to toggle source

Pseudo-translation text to append to fetched strings. Used as a visible marker. Default is “]]”

# File lib/annotranslate.rb, line 224
def self.pseudo_append
  @@pseudo_append
end
pseudo_append=(v) click to toggle source

Set the pseudo-translation text to append to fetched strings. Used as a visible marker.

# File lib/annotranslate.rb, line 230
def self.pseudo_append=(v)
  @@pseudo_append = v
end
pseudo_prepend() click to toggle source

Pseudo-translation text to prepend to fetched strings. Used as a visible marker. Default is “[[”

# File lib/annotranslate.rb, line 212
def self.pseudo_prepend
  @@pseudo_prepend
end
pseudo_prepend=(v) click to toggle source

Set the pseudo-translation text to prepend to fetched strings. Used as a visible marker.

# File lib/annotranslate.rb, line 218
def self.pseudo_prepend=(v)
  @@pseudo_prepend = v
end
pseudo_translate(enable = true) click to toggle source

Toggle a pseudo-translation mode that will prepend / append special text to all fetched strings. This is useful during testing to view pages and visually confirm that strings have been fully extracted into locale bundles.

# File lib/annotranslate.rb, line 201
def self.pseudo_translate(enable = true)
  @@pseudo_translate = enable
end
pseudo_translate?() click to toggle source

If pseudo-translated is enabled

# File lib/annotranslate.rb, line 206
def self.pseudo_translate?
  @@pseudo_translate
end
scope_key_by_partial(key, path) click to toggle source
# File lib/annotranslate.rb, line 139
def self.scope_key_by_partial(key, path)
  if key.to_s.first == "."
    if path
      path.gsub(%r{/_?}, ".") + key.to_s
    else
      error = "Cannot use t(#{key.inspect}) shortcut because path is not available"
      AnnoTranslate.log.error error
      raise error
    end
  else
    key
  end
end
set_missing_translation_callback(&block) click to toggle source

Set an optional block that gets called when there’s a missing translation within a view. This can be used to log missing translations in production.

Block takes two required parameters:

  • exception (original I18n::MissingTranslationData that was raised for the failed translation)

  • key (key that was missing)

  • options (hash of options sent to annotranslate)

Example:

set_missing_translation_callback do |ex, key, options|
  logger.info("Failed to find #{key}")
end
# File lib/annotranslate.rb, line 76
def self.set_missing_translation_callback(&block)
  @@missing_translation_callback = block
end
strict_mode(enable_strict = true) click to toggle source

Toggle whether to true an exception on all MissingTranslationData exceptions Useful during testing to ensure all keys are found. Passing true enables strict mode, false installs the default exception handler which does not raise on MissingTranslationData

# File lib/annotranslate.rb, line 182
def self.strict_mode(enable_strict = true)
  @@strict_mode = enable_strict

  if enable_strict
    # Switch to using contributed exception handler
    I18n.exception_handler = :strict_i18n_exception_handler
  else
    I18n.exception_handler = :default_exception_handler
  end
end
strict_mode?() click to toggle source

Get if it is in strict mode

# File lib/annotranslate.rb, line 194
def self.strict_mode?
  @@strict_mode
end
t(key, options={})
Alias for: translate
tag_helper() click to toggle source
# File lib/annotranslate.rb, line 56
def self.tag_helper
  TagHelper.instance
end
translate(key, options={}) click to toggle source

Generic translate method that mimics I18n.translate (e.g. no automatic scoping) but includes locale fallback and strict mode behavior.

# File lib/annotranslate.rb, line 157
def translate(key, options={})
  AnnoTranslate.translate_with_annotation(key, @virtual_path, options)
end
Also aliased as: t
translate_with_annotation(scope, path, key, options={}) click to toggle source
# File lib/annotranslate.rb, line 80
def self.translate_with_annotation(scope, path, key, options={})
  AnnoTranslate.log.info "translate_with_annotation(scope=#{scope}, path=#{path}, key=#{key}, options=#{options.inspect})"

  scope ||= [] # guard against nil scope

  # Let Rails 2.3 handle keys starting with "."
  # raise AnnoTranslateError, "Skip keys with leading dot" if key.to_s.first == "."

  # Keep the original options clean
  original_scope = scope.dup
  scoped_options = {}.merge(options)

  # Raise to know if the key was found
  scoped_options[:raise] = true

  # Remove any default value when searching with scope
  scoped_options.delete(:default)

  str = nil # the string being looked for

  # Apply scoping to partial keys
  key = AnnoTranslate.scope_key_by_partial(key, path)

  # Loop through each scope until a string is found.
  # Example: starts with scope of [:blog_posts :show] then tries scope [:blog_posts] then
  # without any automatically added scope ("[]").
  while str.nil?
    # Set scope to use for search
    scoped_options[:scope] = scope

    begin
      # try to find key within scope (dup the options because I18n modifies the hash)
      str = I18n.translate(key, scoped_options.dup)
    rescue I18n::MissingTranslationData => exc
      # did not find the string, remove a layer of scoping.
      # break when there are no more layers to remove (pop returns nil)
      break if scope.pop.nil?
    end
  end

  # If a string is not yet found, potentially check the default locale if in fallback mode.
  if str.nil? && AnnoTranslate.fallback? && (I18n.locale != I18n.default_locale) && options[:locale].nil?
    # Recurse original request, but in the context of the default locale
    str ||= AnnoTranslate.translate_with_scope(original_scope, key, options.merge({:locale => I18n.default_locale}))
  end

  # If a string was still not found, fall back to trying original request (gets default behavior)
  str ||= I18n.translate(key, options)

  # If pseudo-translating, prepend / append marker text
  if AnnoTranslate.pseudo_translate? && !str.nil?
    str = AnnoTranslate.pseudo_prepend + str + AnnoTranslate.pseudo_append
  end

  tag = tag_helper.content_tag('span', str, :class => 'translation_annotated', :title => key)
  AnnoTranslate.log.info "  => full_key=#{key}, translation=#{str}, tag=#{tag.inspect}"
  tag
end