Providers & models
locallingo translates through RubyLLM, so any provider it supports works — chosen by config.
Provider-agnostic via RubyLLM#
Every translation and quality-review call goes through RubyLLM, so locallingo isn't tied to one vendor. You pick the provider and models in .locallingo.yml; the rest of the toolchain is identical regardless of which you choose.
Choosing a provider#
Set provider to a RubyLLM provider symbol, and the per-task models under translate and quality.
defaults:
provider: openai # or anthropic, gemini, ...
translate:
model: gpt-5-mini
quality:
model: gpt-4o-minidefaults:
provider: anthropic
translate:
model: claude-haiku-4-5
quality:
model: claude-sonnet-4-6Credentials#
locallingo looks for the configured provider's API key in three places, in order — the first non-blank key wins:
Locallingo.configure— a key set on the gem itself.RubyLLM.configure— a key the host app set on RubyLLM directly (a Rails initializer, typically).- ENV —
OPENAI_API_KEY,ANTHROPIC_API_KEY,GEMINI_API_KEY, and so on.
A plain ENV var is all most setups need. When your key lives somewhere else — Rails credentials, an app config object, a vault — configure the gem from Ruby. Values can be Strings or callables; callables are resolved fresh on every LLM call, never cached:
Locallingo.configure do |config|
config.anthropic_api_key = Rails.application.credentials.anthropic_api_key
config.openai_api_key = -> { AppConf.openai_api_key } # resolved lazily
endStandalone CLI runs
lingo doesn't boot Rails, so an initializer never runs for it. Put the configure call in a .locallingo.rb file next to .locallingo.yml — the CLI loads it before dispatch:
require_relative "config/app_conf"
Locallingo.configure do |config|
config.anthropic_api_key = -> { AppConf.anthropic_api_key }
endlocallingo fails fast with a clear message when no source yields a key, before making any network call.
translate and the optional quality --ai pass call the provider. Everything else runs offline.Two models, two jobs#
translate.modeldoes the bulk translation work — favour a fast, inexpensive model, since it runs over every missing/changed key in batches (translate.batch_size, default 20).quality.modelpowers the optional AI review of existing translations — a stronger model pays off here because it runs on a sample, not the whole corpus.