# -*- encoding : utf-8 -*- require 'phrase/delegate/i18n' class Phrase::Backend::PhraseService attr_accessor :api_client, :blacklisted_keys def initialize(args = {}) self end def translate(*args) if to_be_translated_without_phrase?(args) I18n.translate_without_phrase(*args) else phrase_delegate_for(args) end end protected def to_be_translated_without_phrase?(args) Phrase.disabled? or has_been_given_blacklisted_key?(args) or has_been_given_ignored_key?(args) or has_been_forced_to_resolve_with_phrase?(args) end def has_been_given_blacklisted_key?(args) key = given_key_from_args(args) has_blacklist_entry_for_key?(key) end def has_been_given_ignored_key?(args) key = given_key_from_args(args) key_is_ignored?(key) end def has_been_forced_to_resolve_with_phrase?(args) (args.last.is_a?(Hash) and args.last[:resolve] == false) end def given_key_from_args(args) extract_normalized_key_from_args(args) end def has_blacklist_entry_for_key?(key) blacklisted_keys.each do |blacklisted_key| return true if present?(key.to_s[/\A#{blacklisted_key.gsub("*", ".*")}\Z/]) end false end def key_is_ignored?(key) Phrase.ignored_keys.each do |ignored_key| return true if present?(key.to_s[/\A#{ignored_key.gsub("*", ".*")}\Z/]) end false end def blacklisted_keys @blacklisted_keys ||= api_client.fetch_blacklisted_keys end def api_client @api_client ||= Phrase::Api::Client.new(Phrase.auth_token) end def phrase_delegate_for(args) key = given_key_from_args(args) return nil unless present?(key) options = args[1].nil? ? {} : args[1] Phrase::Delegate::I18n.new(key, options, args) end def extract_normalized_key_from_args(args) transformed_args = transform_args(args) normalized_key(transformed_args) end def transform_args(args) duped_args = args.map { |item| (item.is_a?(Symbol) or item.nil?) ? item : item.dup } transform_args_based_on_caller(duped_args) end def normalized_key(duped_args) splitted_args = split_args(duped_args) key = I18n::Backend::Flatten.normalize_flat_keys(*splitted_args) key.gsub!("..", ".") key.gsub!(/^\./, '') key end def split_args(args) options = options_from_args(args) key ||= args.shift locale = options.delete(:locale) || I18n.locale return [locale, key, options[:scope], nil] end def options_from_args(args) args.last.is_a?(Hash) ? args.pop : {} end def transform_args_based_on_caller(args) translation_caller = identify_caller if translation_caller and args.first =~ /^\./ options = options_from_args(args) if not present?(options[:scope]) and present?(translation_caller) options[:scope] = translation_caller end args.push(options) parts = args.first.to_s.split(".").select { |e| not blank?(e) } args[0] = parts[0] if parts.size == 1 end args end def identify_caller translation_caller = nil send(:caller)[0..6].each do |intermediate_caller| translation_caller = calling_template(intermediate_caller) unless translation_caller end if present?(translation_caller) find_lookup_scope(translation_caller) else nil end end def calling_template(string) string.match(/(views)(\/.+)(?>:[0-9]+:in)/) end def blank?(str) raise "blank?(str) can only be given a String or nil" unless str.is_a?(String) or str.nil? str.nil? or str == '' end def present?(str) raise "present?(str) can only be given a String or nil" unless str.is_a?(String) or str.nil? not blank?(str) end def find_lookup_scope(caller) split_path = caller[2][1..-1].split(".")[0].split("/") template_or_partial = remove_underscore_form_partial(split_path[-1]) split_path[-1] = template_or_partial split_path.map!(&:to_sym) end def remove_underscore_form_partial(template_or_partial) if template_or_partial.to_s[0,1] == "_" template_or_partial.to_s[1..-1] else template_or_partial.to_s end end end