Machine Translations
To enable machine translations you need to enable the service and specify the class used for translation (this usually is the one contacting an external API from a 3d party service that actually translates the string).
class MyTranslationService
attr_reader :text, :source_locale, :target_locale, :resource, :field_name
def initialize(resource, field_name, text, target_locale, source_locale)
@resource = resource
@field_name = field_name
@text = text
@target_locale = target_locale
@source_locale = source_locale
end
def translate
# Actual code for translating the text
translated_text = "#{target_locale} - #{text}"
Decidim::MachineTranslationSaveJob.perform_later(
resource,
field_name,
target_locale,
translated_text
)
end
end
The arguments provided for the initialize method are:
-
resource- The object of the resource that being translated (ex: aDecidim::Meetings::Meetinginstance ) -
field_name- The name of the field that is being translated (ex: "title") -
text- The text that is going to be translated (ex: "This meeting is great" ) -
target_locale- The language in which you want to translate ( ex: "ca" ) -
source_locale- The language in which the content has been created (ex: "en")
Then you will need to configure it with the help of Environment Variables:
export DECIDIM_ENABLE_MACHINE_TRANSLATION="true"
export DECIDIM_MACHINE_TRANSLATION_SERVICE="MyTranslationService"
You also need to enable the setting "Enable machine translations" in Settings → Configuration.
You can read more about the details of how this service work at `Using machine translations.
Examples
LibreTranslate
LibreTranslate is a Free and Open Source Machine Translation API. Self-hosted, offline capable and easy to setup. If you do not want to self-host it, they also offer a paid service at libretranslate.com.
For using it, follow these steps:
-
Install LibreTranslate with any of the methods proposed on their documentation. For demonstration purposes, it will be installed at
http://localhost:5000. You have a Docker Compose configuration based on the LibreTranslate documentation. -
Add the file
app/services/libre_translate_service.rbto your application -
Add these Environment Variables:
export DECIDIM_ENABLE_MACHINE_TRANSLATION="true" export DECIDIM_MACHINE_TRANSLATION_SERVICE="LibreTranslateService" export DECIDIM_LIBRE_TRANSLATE_SERVICE_URL="http://localhost:5000"
-
Restart the web application and queue servers
-
Sign in as administrator
-
Go to the admin panel and go into in
Settings→Configuration -
Enable the settings "Enable machine translations" and "Translated text first"
-
Create a new Process or Edit an existing one
-
Go to the frontend and change the language
Docker compose
services:
libretranslate:
image: libretranslate/libretranslate
container_name: libretranslate
ports:
- "${LT_PORT:-5000}:5000"
volumes:
- lt-local:/home/libretranslate/.local
# Uncomment the line below if using --api-keys
# - lt-db:/app/db
stdin_open: true
tty: true
restart: unless-stopped
# Add any additional command arguments here
# command: ["--api-keys"]
volumes:
lt-local:
name: lt-local
app/services/libre_translate_service.rb
# frozen_string_literal: true
require "faraday"
require "json"
# This translator uses LibreTranslate API to translate text
# from one locale to another.
class LibreTranslateService
attr_reader :text, :source_locale, :target_locale, :resource, :field_name
def initialize(resource, field_name, text, target_locale, source_locale)
@resource = resource
@field_name = field_name
@text = text
@target_locale = target_locale
@source_locale = source_locale
end
def translate
translated_text = fetch_translation || text
Decidim::MachineTranslationSaveJob.perform_later(
resource,
field_name,
target_locale,
translated_text
)
end
private
def fetch_translation
response = Faraday.post("#{host}/translate") do |req|
req.headers["Content-Type"] = "application/json"
req.body = translation_payload.to_json
end
parse_response(response)
rescue => e
log_error(e)
nil
end
def translation_payload
{
q: text,
source: source_locale,
target: target_locale,
api_key: api_key
}.compact
end
def parse_response(response)
result = JSON.parse(response.body)
result["translatedText"]
end
def host
Decidim::Env.new("DECIDIM_LIBRE_TRANSLATE_SERVICE_URL", "https://libretranslate.com").value
end
def api_key
Decidim::Env.new("DECIDIM_LIBRE_TRANSLATE_API_KEY").value
end
def log_error(error)
Rails.logger.error("LibreTranslate translation error: #{error.message}")
end
end