Reputation: 9055
I'm trying to translate my website in all languages supported by Google Translate.
I'm using Ruby on Rails 6, and want to do it as a translation backend, but this is not specific to Ruby or Ruby on Rails.
When I had to support 6 languages I would correct the mistakes myself but I can't
I tried different things but my latest strategy has been storing everything in the database:
class ActiveRecordBackend
include I18n::Backend::Base
include I18n::Backend::Transliterator
SEPARATE_INTERPOLATIONS = /(?<interpolation>%{[^}]+})|(?<text>[^%]+)/
NETWORK_ERRORS = [SocketError, Errno::EHOSTUNREACH].freeze
LOCALES_PATH = Rails.root.join("lib/data/locales.yml")
LOCALES = YAML.safe_load(LOCALES_PATH.read).map(&:to_struct).sort_by(&:name)
LOCALE_NAMES = LOCALES.map(&:locale).map(&:to_sym)
def available_locales
LOCALE_NAMES
end
def reload!
@translations = nil
self
end
def initialized?
[email protected]?
end
def init_translations
@translations = Translation.to_hash
end
def translations(do_init: false)
init_translations if do_init || !initialized?
@translations ||= {}
end
private
def lookup(locale, key, _scope = [], _options = {})
Translation.find_by(locale: locale, key: key)&.value ||
store_translation(locale: locale, key: key)
end
def store_translation(locale:, key:)
default = Translation.find_by(locale: I18n.default_locale, key: key)
return unless default
translated_value =
easy_translate(default.value, from: I18n.default_locale, to: locale)
return unless translated_value
Translation.find_or_create_by(
locale: locale,
key: key,
value: translated_value
)
translated_value
end
def easy_translate(original, from:, to:)
original
.scan(SEPARATE_INTERPOLATIONS)
.map do |interpolation, text|
next interpolation if interpolation
spaces_before = text.scan(/\A */).first
spaces_after = text.scan(/ *\z/).first
translated_text =
EasyTranslate.translate(text, from: from, to: to).strip
"#{spaces_before}#{translated_text}#{spaces_after}"
end
.join
rescue *NETWORK_ERRORS, EasyTranslate::EasyTranslateException
nil
end
end
But I get things like
"<b>7976membri attivi tra cui1in linea<br>562attività con5945partecipazioni"
for italian
instead of:
"<b>7976</b> membres actifs dont <b>1</b> en ligne <br><b>562</b> activités avec <b>5945</b> participations"
for french
And I also don't handle returning a group of translations like t(".js")
.
How would you do it?
Upvotes: 0
Views: 540
Reputation: 9055
I found a solution:
def easy_translate(original, from:, to:)
interpolations_in_original = original.scan(INTERPOLATION)
spaces_before = original.scan(/\A */).first
spaces_after = original.scan(/ *\z/).first
translated_text = EasyTranslate.translate(original, from: from, to: to).strip
translated_text = translated_text.gsub("% {", "%{")
bad_interpolations = translated_text.scan(INTERPOLATION)
interpolations_in_original.size.times do |index|
translated_text.gsub!(bad_interpolations[index], interpolations_in_original[index])
end
"#{spaces_before}#{translated_text}#{spaces_after}"
rescue *NETWORK_ERRORS, EasyTranslate::EasyTranslateException
nil
end
Can be improved obviously like actually replacing each interpolation by the corresponding correct one and keeping capitalization
Upvotes: 0
Reputation: 28285
How would you do it?
I wouldn't do it.
If your website only natively supports a few languages (e.g. English) and a user wants to view it in an unsupported language (e.g. Italian), then let the user apply Google Translation themselves.
There's a very popular plugin to do this. But, like you found already, it won't always give perfect results: Sometimes it can mess up your page layout, in addition to just giving sub-optimal translations due to mis-interpreted context.
If you discover a magic way to accurately apply website translations in the backend to all possible languages and contexts, without breaking the UI, then congratulations -- you'll soon be incredibly wealthy.
Upvotes: 1
Reputation: 310
Agree with @GiacomoCatenazzi, it looks very unprofessional to have obvious spelling mistakes. If you have to translate the page, I recommend you use I18n and do it manually.
If you feel like you have to use GT, I would do something like this:
You can improve the amount of requests in step 4 as much as you want, with some dedication it should be possible to limit the requests to the amount of languages you support.
Upvotes: 0