Discourse Translator

:discourse2: Summary Discourse Translator translates posts on Discourse using Microsoft, Google, or Yandex translation APIs.
:hammer_and_wrench: Repository Link https://github.com/discourse/discourse-translator
:open_book: Install Guide How to install plugins in Discourse

Features

  • Each post is only translated once per locale which saves you :moneybag:
    • Note that language detection is also run once for every post. Be careful when enabling this on old and large forums.
  • Access Token is cached server side for faster translations.
  • Translations are rate limited to 3 per minute by default (admins can configure this value)

Translation Services Supported

Configuration Steps

Microsoft
  1. Follow the steps in Microsoft Translator API on Azure to obtain a subscription key. You may pick from any of the available subscription offers.

  2. In your Discourse, under Admin > Settings > Plugins, enter the subscription key that you’ve obtained from the steps above.

  1. In your Discourse, under Admin > Settings > Basic Setup, enable allow user locale.
Google Translator
  1. Go to https://console.developers.google.com

  2. Click on My Project

  1. Click on the :heavy_plus_sign: to create a new project

  1. Enter your project name and click create

  2. Select Enable API and search for Google Cloud Translator API. Look for the enable button and click it to enable the API. Note that there is no free tier for the Google Translator API so it may prompt you to enable billing.

  3. Once you’re done, click on credentials in the left menu

  1. Click create credentials and select API key. Copy the API Key and paste it into the translator google api key site setting in Discourse.

  2. In Discourse, under Admin > Settings > Basic Setup, enable allow user locale.

Settings

Name Description
translator enabled Allow inline translation of posts.
translator The provider of the translation service.
translator azure subscription key Azure Subscription Key
translator azure region Azure Region
translator azure custom subdomain Required if using a Virtual Network or Firewall for Azure Cognitive Services. Note: Only enter the custom subdomain not the full custom endpoint.
translator aws region AWS Region
translator aws key id AWS Key ID
translator aws secret access AWS secret access key
translator aws iam role AWS IAM Role
translator google api key Google API Key
translator yandex api key Yandex API Key
translator libretranslate endpoint LibreTranslate Endpoint
translator libretranslate api key LibreTranslate API Key
max translations per minute The number of translations per minute a regular user can perform.
restrict translation by group Only allowlisted groups can translate
restrict translation by poster group Only allow translation of posts made by allowlisted users

Known Issues

  • Does not translate text within polls generated by discourse-poll plugin.
  • Images are enlarged upon translating.

:discourse2: Hosted by us? This plugin is available on our Enterprise plan.

Last edited by @JammyDodger 2024-06-18T14:19:34Z

Check documentPerform check on document:
103 лайка
Advice for bilingual communities
Inline translation of posts into another language
Language Translation
Can we have have one post with two different language
Plugin for signatures?
Translate plugin installed, but no translate button
LibreTranslate Plugin -- Free and Open Source Translation API
Discourse Translator plugin is not showing for non-logged in users
What exactly are the effects of "allow user locale"
DeepL integration for Translator plugin
How do you use Discourse AI? Tell us and make it even better!
How do I get the forum here in German
Is Google translate really so expensive?
Anyone migrated to version 3 of Microsoft Translator API yet?
Moving up the translator icon
Image zoom is not working
Translating text in polls
Yandex Translation Service
Anyone Using Discourse Translator Plugin on small forum, Cost/month?
FYI, Full translation of Discourse including posts is possible
Mute ALL other languages
How to install a plugin on Discourse-hosted-Discourse?
Make a multi-language forum
How to handle users that don't really read the answers they get?
Localized email templates
Translates to user's local language
DeepL integration for Translator plugin
Javascript pop up block help
No errors, instance not coming back up after rebuild
DeepL support for Discourse Translator
Getting user profile custom field via JS
Google Translate shows "blank" page
What exactly are the effects of "allow user locale"
Virtual Keyboard hides critical editor buttons for 3.3.0-beta
Translation from Lugandan yields uncaught 500 error (in a different Discourse)
Is Automatic Translation for Most Content Now Official?
Everything is translated, help!
Virtual Keyboard hides critical editor buttons for 3.3.0-beta
Translation support about the topic content
Translates to user's local language
Structuring a multilingual community
Translate email notifications and digests into user preferred locale language
Implementing In-House Translation Features on Discourse
Include translated posts in search?
Translate email notifications and digests into user preferred locale language
Changing default language will not change the site TITLE or DESCRIPTION!
Yandex Translation Service
Simple idea for translator-assisted bilingual forum
MKJ's Opinionated Discourse Deployment Configuration
Help which plugin is in the screenshot
Übersetzung wie hier auf Meta

Пост был разделен на новую тему: Я ищу такое решение, чтобы использовать LLM для перевода лучших постов моего форума

Сообщение было разделено на новую тему: Добавление опции для отдельной конфигурации службы обнаружения языка

Пост был разделён на новую тему: Используются ли форумы, размещённые на Discourse, локальным экземпляром LibreTranslate?

Я использую саморазмещённую версию LibreTranslate, которая раньше работала отлично, но сейчас я получаю множество повторяющихся ошибок «Job exception: The translator service is currently not available» (Исключение задания: сервис перевода в настоящее время недоступен). Я проверил URL-адрес, который раньше работал без проблем. Если открыть этот URL, страница веб-интерфейса LibreTranslate отображается корректно. API-токен не требуется, так как мой экземпляр LibreTranslate является приватным и не доступен из интернета.

Вот трассировка стека:

Сообщение (548 дубликатов)

Исключение задания: сервис перевода в настоящее время недоступен.

Трассировка стека

/var/www/discourse/plugins/discourse-translator/services/discourse_translator/libretranslate.rb:168:in `result'
/var/www/discourse/plugins/discourse-translator/services/discourse_translator/libretranslate.rb:85:in `detect'
/var/www/discourse/plugins/discourse-translator/plugin.rb:120:in `block in execute'
/var/www/discourse/lib/distributed_mutex.rb:53:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:49:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:49:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:34:in `synchronize'
/var/www/discourse/plugins/discourse-translator/plugin.rb:119:in `execute'
/var/www/discourse/app/jobs/base.rb:305:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.0.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.0.0/lib/rails_multisite/connection_management.rb:21:in `with_connection'
/var/www/discourse/app/jobs/base.rb:292:in `block in perform'
/var/www/discourse/app/jobs/base.rb:288:in `each'
/var/www/discourse/app/jobs/base.rb:288:in `perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:202:in `execute_job'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:170:in `block (2 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:177:in `block in invoke'
/var/www/discourse/lib/sidekiq/pausable.rb:132:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:179:in `block in invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:182:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:169:in `block in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:136:in `block (6 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/job_retry.rb:113:in `local'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:135:in `block (5 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq.rb:44:in `block in <module:Sidekiq>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:131:in `block (4 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:263:in `stats'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:126:in `block (3 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/job_logger.rb:13:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:125:in `block (2 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/job_retry.rb:80:in `global'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:124:in `block in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/job_logger.rb:39:in `prepare'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:123:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:168:in `process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:78:in `process_one'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/processor.rb:68:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/component.rb:8:in `watchdog'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-6.5.12/lib/sidekiq/component.rb:17:in `block in safe_thread'

Есть ли у кого-нибудь идеи, как это исправить?

2 лайка

Вариант локализации «Hindi» пока недоступен в «Discourse». Однако перевод на «Hindi» доступен через другие сервисы (я использую «Microsoft Azure»).

Как тогда настроить автоматический перевод всех/любых постов, не на «Hindi», на «Hindi», даже если интерфейс Discourse остаётся на английском? Возможно ли это вообще?

1 лайк

Пытаюсь также перенести этот вопрос на их форум Discourse.

3 лайка

Я подумываю о добавлении этого переводчика на наш форум. Однако у меня есть два основных опасения:

1. Можно ли изменять переводы?
Я хочу убедиться, что определённые термины переводятся нужным образом. Для этого мне нужна возможность просматривать доступные переводы и при необходимости вносить в них изменения.

2. Когда пост будет переведён заново?
Некоторые сообщения на форуме редактируются довольно часто. Как мне гарантировать, что каждая исправленная опечатка не приведёт к непомерным затратам на перевод? Кроме того, как обеспечить, чтобы новые изменения точно отражались в переводах?

3 лайка

Полагаю, это невозможно, так как потребовалось бы вмешательство на уровне поставщика услуг (Microsoft/Google). Если только переведённый контент не подпадает под функцию замены слов, тогда можно воспользоваться ею.

Вот предложение по улучшению:

  1. Автоматически переводить первый пост на английский язык, если он написан на другом языке.
  2. Добавить кнопку для перевода всей темы сразу.
  3. Включить функцию автоматического перевода для всего форума на уровне пользователя. Это означает, что если пользователь укажет в своём профиле, что он говорит, например, только на румынском, то весь контент будет переводиться на румынский. Если он укажет, что владеет несколькими языками, посты будут переводиться только в том случае, если они не на этих языках.
2 лайка

Как администратор сайта, я был удивлён, прочитав это:

Где находится эта скрытая настройка? :smiling_face_with_sunglasses:

1 лайк
./launcher enter app
rails c
SiteSetting.automatic_translation_backfill_rate = <нужное значение>
exit
exit

Но, кажется, его больше нет, по крайней мере в более новых версиях.

2 лайка

Как вы этому учитесь? :sweat_smile: Ладно, спасибо! Я подожду ответа от команды, чтобы убедиться.

1 лайк

Два способа: с помощью поиска и ask.discourse.com

3 лайка
3 лайка

Уведомления о темах с заголовками, которые были переведены, не отображаются в переведённом виде в панели уведомлений:

1 лайк

Также мой пост был переведен на неправильный язык по ссылке?


Посмотрев в редакторе, вот что я на самом деле написал:

Я также заметил, что при переводе не сработало однобоковое отображение (oneboxing).

1 лайк

Уведомление на вашем скриншоте использует оригинальное название темы вашего поста, поэтому сейчас оно «верное». В будущем мы обеспечим перевод уведомлений (названий тем).

Что касается поста выше, наша машинная система перевода дала сбой: пост был ошибочно определен как «испанский (es)», а затем переведён некорректно. Это исправлено. Мы работаем над улучшением переводов, используя более качественные промпты.

2 лайка

Я получил эту ошибку при установке плагина discourse-translator. Моя версия Discourse — 3.5.0.beta1.

I, [2025-04-24T01:33:20.510994 #1]  INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate'
        82: from /usr/local/bin/bundle:25:in `<main>'
        81: from /usr/local/bin/bundle:25:in `load'
        80: from /usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:20:in `<top (required)>'
     ....
        10: from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/lazy_load_hooks.rb:87:in `with_execution_control'
        9: from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/lazy_load_hooks.rb:94:in `block in execute_hook'
        8: from /var/www/discourse/config/application.rb:249:in `block in <class:Application>'
        7: from /var/www/discourse/lib/plugin.rb:6:in `initialization_guard'
        6: from /var/www/discourse/config/application.rb:249:in `block (2 levels) in <class:Application>'
        5: from /var/www/discourse/config/application.rb:249:in `each'
        4: from /var/www/discourse/lib/plugin/instance.rb:629:in `notify_after_initialize'
        3: from /var/www/discourse/lib/plugin/instance.rb:629:in `each'
        2: from /var/www/discourse/lib/plugin/instance.rb:631:in `block in notify_after_initialize'
        1: from /var/www/discourse/plugins/discourse-translator/plugin.rb:40:in `block in activate!'
/var/www/discourse/plugins/discourse-translator/lib/discourse_translator/inline_translation.rb:86:in `inject': protected method `register_topic_preloader_associations' called for an instance of Plugin::Instance (NoMethodError)

Как это исправить?

1 лайк

Привет! Ошибку можно устранить, обновив сначала Discourse, а затем устанавливая плагин.

Метод register_topic_preloader_associations был перемещён из категории protected в public.

4 лайка

Спасибо, я успешно установил после обновления Discourse до последней версии.

2 лайка