@rithien/factorio-translate
v0.5.1
Published
Plugin Clusterio: ADAPTYWNE tłumaczenie czatu Factorio na języki połączonych graczy. Scenariusz emituje tag [FP-TRANSLATE] (zbiór locale graczy); plugin tłumaczy równolegle na każdy obecny język (LibreTranslate lub Google) i odsyła /fpo {speaker,original,
Downloads
689
Maintainers
Readme
@rithien/factorio-translate — adaptywny tłumacz czatu Factorio
Plugin Clusterio: adaptywnie tłumaczy czat na języki
aktualnie połączonych graczy przez wybrany backend —
LibreTranslate albo
Google Cloud Translate (v2 Basic).
Backend wybiera się jednym polem konfiguracji (translator_backend — dropdown w web panelu clusterio).
Model (scenario-only — wymaga scenariusza factorio-polska):
- Scenariusz hookuje
on_console_chat, zbiera zbiór locale połączonych graczy i — gdy są ≥2 różne locale — emituje na stdout tag[FP-TRANSLATE]{speaker,text,locales}. Gdy wszyscy mają to samo locale, nic nie emituje („same locale → nie tłumaczymy" = zero kosztu API). - Plugin czyta ten tag, wykrywa język źródła (
/detect,confidence > min_confidence) i tłumaczy równolegle na każde obecne locale (≠ źródło) oraz na języki uniwersalnej linii czatu. - Plugin odsyła JEDEN payload
/fpo {speaker, original, t, chat}:- overhead — scenariusz renderuje nad głową każdego odbiorcy wariant
t[jego locale](fallback: oryginał), czyli każdy widzi wiadomość w swoim języku; - chat — jedna uniwersalna linia tłumaczenia na czacie dla wszystkich: segment per język z pola
chat_languages(pl+en/pl/en), np.Banshee [pl] Cześć [en] Hello; segment języka == język źródła jest pomijany (oryginał i tak jest na czacie natywnie).
- overhead — scenariusz renderuje nad głową każdego odbiorcy wariant
Fallback: brak detekcji / literówka / nazwa własna → nad głową leci oryginał; na czat zawsze oryginał.
Bez patchowania save'a — brak folderu module/, działa niezależnie od factorio.enable_save_patching.
Komenda wyjścia /fpo to custom command (jak /fp) → w przeciwieństwie do /c//sc
nie wyłącza achievementów.
Wymaga scenariusza factorio-polska z
lib/translate_chat_emit.lua+ kontraktem/fpo{speaker,original,t,chat}(wersja wprowadzająca adaptive). Plugin i scenariusz deployują się RAZEM — kontrakt/fpozmienił się względem starego{pl,en}. Bez kompatybilnego scenariusza tłumaczenia nie pojawią się w grze (plugin nie ubije serwera — sytuacja jest logowana).
Opis kanałów komunikacji z grą: Plugin_comunication.md. Wytyczne
implementacyjne: CLAUDE.md.
Struktura
factorio-translate/
├── index.js # eksport `plugin` (nazwa, entrypointy, instanceConfigFields)
├── instance.js # InstancePlugin: onOutput ([FP-TRANSLATE]) -> detect + równoległe translate
│ # -> sendRcon(/fpo {speaker,original,t,chat}); factorioToCanonical, planTranslation
├── outputs/ # warstwa wyjścia (scenario-only)
│ ├── index.js # re-eksport { buildFpoCommand, sanitizeText }
│ ├── scenario.js # buildFpoCommand(...) — /fpo <json>
│ └── util.js # sanitizeText(text, max)
├── translators/ # warstwa backendów (wspólny kontrakt: configured / detect / translate)
│ ├── index.js # createTranslator(opts) — fabryka wybierająca backend wg translator_backend
│ ├── http.js # wspólny postJson() — fetch + timeout + normalizacja błędów (nie loguje klucza)
│ ├── libretranslate.js # klient LibreTranslate (detect kanonizuje kod języka)
│ └── google.js # klient Google Cloud Translation v2 Basic (kanon → kod Google, np. zh→zh-CN)
├── controller.js # ControllerPlugin — stub (na razie nic istotnego)
├── package.json # Node >= 18 (globalny fetch)
├── test/plugin.js # mocha
├── Plugin_comunication.md # dokumentacja kanałów komunikacji z grą
├── CLAUDE.md # wytyczne implementacyjne
└── (CELOWO brak module/) # save NIE jest patchowanyInstalacja
Wymagania wstępne
- Działający klaster Clusterio 2.x (kontroler + co najmniej jeden host z instancją Factorio).
- Node.js ≥ 18 (plugin używa globalnego
fetch). - Scenariusz factorio-polska z
lib/translate_chat_emit.luai kontraktem/fpo {speaker,original,t,chat}na danej instancji. - Dostęp do jednego z backendów tłumaczeń:
- LibreTranslate — własna instancja albo publiczna/płatna z kluczem, lub
- Google Cloud Translate — projekt Google Cloud z włączonym Cloud Translation API i kluczem API.
- Plugin nie wymaga
factorio.enable_save_patching— działa niezależnie od tej opcji.
1. Zainstaluj plugin z npm
W katalogu instalacji Clusterio (ten z node_modules/@clusterio/..., config-controller.json itd.):
npm install @rithien/factorio-translate2. Zarejestruj plugin w każdym komponencie
npx clusteriocontroller plugin add @rithien/factorio-translate
npx clusteriohost plugin add @rithien/factorio-translate
npx clusterioctl plugin add @rithien/factorio-translate3. Zrestartuj kontroler i hosta
Zatrzymaj i uruchom ponownie procesy kontrolera oraz hosta, żeby załadowały plugin. Plugin „wejdzie" do działającej instancji dopiero przy jej restarcie (krok 5).
4. Skonfiguruj instancję
Wybierz backend polem factorio-translate.translator_backend (libretranslate — domyślny — albo
google) i uzupełnij pola odpowiednie dla wybranego backendu.
Backend LibreTranslate (minimum to translator_api_url):
npx clusterioctl instance config set <instancja> factorio-translate.translator_backend libretranslate
npx clusterioctl instance config set <instancja> factorio-translate.translator_api_url https://libretranslate.example
# jeśli Twoja instancja LibreTranslate wymaga klucza:
npx clusterioctl instance config set <instancja> factorio-translate.translator_api_key <klucz>Backend Google Cloud Translate (minimum to google_api_key):
npx clusterioctl instance config set <instancja> factorio-translate.translator_backend google
npx clusterioctl instance config set <instancja> factorio-translate.google_api_key <klucz-google-cloud>Języki uniwersalnej linii czatu (pl+en = segmenty [pl] i [en] w jednej linii, albo tylko pl /
tylko en):
npx clusterioctl instance config set <instancja> factorio-translate.chat_languages pl+enZmiany backendu / URL / kluczy / timeoutu są podchwytywane na żywo (bez restartu instancji).
5. Uruchom (lub zrestartuj) instancję ze scenariuszem factorio-polska
npx clusterioctl instance start <instancja>Aktualizacja / odinstalowanie
- Aktualizacja:
npm install @rithien/factorio-translate@latest, restart kontrolera i hosta, restart instancji. Deployuj razem z kompatybilnym scenariuszem (kontrakt/fpo). - Odinstalowanie:
plugin remove @rithien/factorio-translatew każdym komponencie, restart kontrolera i hosta.
Konfiguracja (instancja, prefiks factorio-translate.)
| Pole | Typ | Domyślnie | Opis |
|---|---|---|---|
| enabled | boolean | true | Master kosztowy: gdy ON plugin woła płatne API. Wyłącz, by zatrzymać koszty |
| chat_languages | enum | pl+en | Języki JEDNEJ uniwersalnej linii na czacie (pl+en/pl/en); segment == język źródła pomijany. Niezależne od overheadu (per-widz) |
| translator_backend | enum | libretranslate | Backend tłumaczeń: libretranslate lub google (dropdown) |
| translator_api_url | string | "" | [libretranslate] Bazowy URL, bez końcowego /. Puste = backend nieaktywny |
| translator_api_key | string | "" | [libretranslate] Klucz API; puste = bez klucza. Nie jest logowany |
| google_api_key | string | "" | [google] Klucz Google Cloud (Cloud Translation API). Puste = nieaktywny. Nie jest logowany |
| min_confidence | number | 90 | Próg confidence z /detect (0–100); tłumaczymy gdy > min_confidence. Google: 0–1 → ×100, brak → 100 |
| request_timeout_ms | number | 5000 | Timeout pojedynczego żądania HTTP |
| min_message_length | number | 1 | Minimalna długość wiadomości, by ją tłumaczyć |
| max_output_length | number | 500 | Sanity-cap na długość każdego pola tekstowego payloadu /fpo (anti-flood + RCON line) |
Zmiana translator_backend / translator_api_url / translator_api_key / google_api_key /
request_timeout_ms jest podchwytywana na żywo (bez restartu instancji).
Jak to działa (przepływ jednej wiadomości)
- Scenariusz (
on_console_chat) emituje[FP-TRANSLATE]{speaker,text,locales}— tylko gdy ≥2 różne locale wśród połączonych graczy. - Plugin
onOutputmatchuje tag i parsuje JSON. POST /detect→ kanoniczny kod języka źródła;confidence <= min_confidence→ forward samego oryginału.- Cele = (kanoniczne locale obecnych ≠ źródło) ∪ (chat_languages \ {źródło}). Tłumaczenie celów
równolegle (
POST /translate, z cache). sendRcon('/fpo ' + JSON({speaker, original, t, chat}), true)— jeden payload na wiadomość.- Scenariusz: nad głową każdego odbiorcy
t[jego locale](fallback oryginał) i/lub uniwersalna liniachatna czacie (togglowane w admin-panelu:translate_overhead/translate_chat).
Błąd backendu (sieć, timeout, 4xx/5xx) → log warn, dane locale lecą bez tego tłumaczenia (fallback
oryginał); serwer nieruszony. Mapowanie kodów: Factorio zh-CN→kanon zh w pluginie; mapa t
pozostaje kluczowana surowym locale (scenariusz robi t[p.locale]); specyfikę backendu (Google
chce zh-CN) obsługują translators/*.js.
Dlaczego /fpo (custom command)
Wbudowane /sc (silent-command) i /c ustawiają trwałą flagę "Cheats have been enabled" na save'ie
— permanentnie wyłączają achievementy. Custom commandy zarejestrowane przez commands.add_command
w Lua nie liczą się jako cheats. Scenariusz factorio-polska rejestruje /fpo (server-only,
RCON-only) jako parser JSON-payloadu (scenario/commands/fpo.lua). Plugin wysyła /fpo <json> i
treść trafia do gry bez setowania cheat flagi.
Uwagi
- Plugin nie kasuje oryginalnej wiadomości — oryginał jest na czacie natywnie; plugin dokłada overhead per-widz + jedną uniwersalną linię tłumaczenia.
- Kolejność wysłanych tłumaczeń między wiadomościami może odbiegać od kolejności wpisania (różna
latencja API). W obrębie jednej wiadomości payload jest atomowy (jeden
/fpo). - LibreTranslate: dla sensownego limitu zapytań użyj własnej instancji albo płatnego klucza — publiczne instancje bywają mocno rate-limitowane (HTTP 429 → dane tłumaczenie pominięte).
- Google Cloud Translate: API v2 (Basic), uwierzytelnianie kluczem API (
?key=), nie v3. Cloud Translation to usługa płatna — pilnuj limitów/budżetu. Klucz najlepiej ogranicz do Cloud Translation API.
Testy
npm install
npm test