class Translatomatic::Translation::Collection
Stores results of translations. For each original text, there may be zero or more translations from one or more providers.
Public Class Methods
Create a translation collection
# File lib/translatomatic/translation/collection.rb, line 10 def initialize # by_provider[provider] = [Result, ...] @by_provider = {} # by_original[text] = [Result, ...] @by_original = {} end
Public Instance Methods
Combine this collection with another @param other [Collection] Another collection @return [Collection] The collection result
# File lib/translatomatic/translation/collection.rb, line 119 def +(other) result = self.class.new @by_provider.each_value { |i| result.add(i) } other.translations.each { |i| result.add(i) } result end
@param string [String,Text] Original string @return [Array<Result>] All translations for the given string
# File lib/translatomatic/translation/collection.rb, line 19 def [](string) @by_original[string.to_s] end
Add a list of translations to the collection @param translations [Array<Result>] Translation
results @return [void]
# File lib/translatomatic/translation/collection.rb, line 44 def add(translations) translations = [translations] unless translations.is_a?(Array) translations.each do |tr| next if tr.result.nil? add_to_list(@by_provider, tr.provider, tr) add_to_list(@by_original, tr.original, tr) end end
@return [Array<Result>] Best translations for each string @param locale [Locale] Target locale
# File lib/translatomatic/translation/collection.rb, line 106 def best_translations(locale) @by_original.keys.collect { |i| get(i, locale) } end
@return [Number] The number of translations
# File lib/translatomatic/translation/collection.rb, line 54 def count translations.length end
@return [String] String description of all translations
# File lib/translatomatic/translation/collection.rb, line 135 def description translations.collect(&:description).join("\n") end
# File lib/translatomatic/translation/collection.rb, line 23 def empty? @by_original.empty? end
Return a new collection with only the translations that came from providers (not from the database). @return [Collection] The collection result
# File lib/translatomatic/translation/collection.rb, line 97 def from_providers result = self.class.new provider_translations = translations.reject(&:from_database) result.add(provider_translations) result end
@param string [String,Text] Original string @param locale [Locale] Target locale @return [Result] The best translation for the given string
# File lib/translatomatic/translation/collection.rb, line 30 def get(string, locale) locale = build_locale(locale) list = @by_original[string.to_s] || [] list = sort_by_best_match(list) if string.is_a?(Translatomatic::Text) && string.context # string has a context list = sort_by_context_match(list, string.context, locale) end list.find { |i| i.result.locale == locale } end
@return [Boolean] True if there is one or more translations
# File lib/translatomatic/translation/collection.rb, line 59 def present? count > 0 end
@return [Array<String>] A list of providers that translations were
sourced from.
# File lib/translatomatic/translation/collection.rb, line 112 def providers @by_provider.keys end
Get a list of the best sentence translations for the given parent string. @param parent [Text] Parent text @param locale [Locale] Target locale @return [Array<Result>] Substring translation results
# File lib/translatomatic/translation/collection.rb, line 81 def sentences(parent, locale) parent.sentences.collect do |sentence| # get translation for sentence translation = get(sentence, locale) # create a new translation with the sentence as the original # string, so that we can rely on the offset value. if translation Result.new(sentence, translation.result, translation.provider, from_database: translation.from_database) end end.compact end
@param string [String,Text] Original string @param provider [String] Provider
name @return [boolean] True if there is a translation for the given string.
# File lib/translatomatic/translation/collection.rb, line 129 def translated?(string, provider) list = @by_provider[provider.to_s] || [] list.any? { |tr| tr.original.to_s == string.to_s } end
Get translations from this collection. If provider is specified, returns only translations from the given provider, otherwise all translations are returned. @param provider [String] Optional name of a provider. @return [Array<Result>] Translation
results
# File lib/translatomatic/translation/collection.rb, line 68 def translations(provider = nil) if provider.nil? @by_provider.values.flatten else @by_provider[provider.to_s] || [] end end
Private Instance Methods
# File lib/translatomatic/translation/collection.rb, line 193 def add_to_list(hash, key, value) list = hash[key.to_s] ||= [] list << value end
@param list [Array<Result>] translations @param context [Array<String>] context(s) @return [Array<String>] lowercased context translation strings
# File lib/translatomatic/translation/collection.rb, line 184 def context_translation_results(list, context, locale) context_locale = list[0].original.locale context = [context] unless context.is_a?(Array) context.collect do |ctx| context_tr = get(Text[ctx, context_locale], locale) context_tr.result.downcase if context_tr end.compact end
sort the list of translations by finding the most common translation. if there is an equal number of different translations use the first most common translation (first provider).
# File lib/translatomatic/translation/collection.rb, line 167 def sort_by_best_match(list) by_count = {} list.each do |tr| key = tr.result.downcase by_count[key] = (by_count[key] || 0) + 1 end # not using sort_by to maintain original sort order # unless count is different. list.sort do |tr1, tr2| by_count[tr1.result.downcase] <=> by_count[tr2.result.downcase] end end
sort the list of translations by comparing to the translation for the string context. for example:
context is 'go right' with a translation of 'Geh rechts'. translation of 'right' is 'rechts', and 'richtig'. translation 'rechts' will be ordered first, as 'rechts' is in the translated context string (and is longer than 'recht').
# File lib/translatomatic/translation/collection.rb, line 150 def sort_by_context_match(list, context, locale) return list if list.blank? context_results = context_translation_results(list, context, locale) # log.debug("context translations: #{context_results}") # put translations that include the context string(s) first. # also put longer translations that include the context string first. # (fixes matching 'rechts' before 'recht') list.sort_by do |tr| tr_result = tr.result.downcase ctx_match = context_results.any? { |ctx| ctx.include?(tr_result) } ctx_match ? -tr_result.length : 1 end end