Compare commits
29 Commits
832a92783b
..
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
b4359c0458
|
|||
| 4dabcaa13c | |||
| 2268334c30 | |||
| 645b8b070b | |||
| adb306604c | |||
| 2e4d074bfc | |||
| 025db00c6a | |||
| 92f964920a | |||
| 58c2e76603 | |||
| 1f8d003f7b | |||
| 5660fabb1a | |||
| 3bc1759c0e | |||
| 83f9e5519f | |||
| 50befc68f2 | |||
| a1bef582f8 | |||
| fdd0a7c6a7 | |||
| 28f85f5809 | |||
| 163f4479a2 | |||
| 92fcd08c8a | |||
| 73008ca1d9 | |||
| 80e2b55887 | |||
| 8c06b2a5f2 | |||
| 7a49f50c65 | |||
| 8597d10e1b | |||
| d6ca4e1415 | |||
| 5633d68a91 | |||
| 3b18c156f1 | |||
| 3344dabf67 | |||
| 854eee4275 |
@@ -0,0 +1,32 @@
|
||||
# Changelog
|
||||
|
||||
Kept as the work happens, not assembled at release time. Format is
|
||||
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
||||
[SemVer](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 1.0.0 — 2026-08-08
|
||||
|
||||
The first tagged version: *Outer Wilds* and *Echoes of the Eye* are translated,
|
||||
which is what this mod set out to do.
|
||||
|
||||
### Added
|
||||
|
||||
- Slovak localization of *Outer Wilds* and *Echoes of the Eye*, as an OWML mod
|
||||
built on `xen.LocalizationUtility`.
|
||||
- A fixed glossary of proper nouns and recurring terms, so names stay consistent
|
||||
across the whole script.
|
||||
|
||||
### Changed
|
||||
|
||||
- The documentation left the repository. The working notes, the phase roadmap,
|
||||
the glossary and the in-game review notes are now the
|
||||
[wiki](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki),
|
||||
and the history was rewritten in the same pass so they are not present at any
|
||||
commit. `assets/Translation.xml` stays here — it ships with the mod.
|
||||
|
||||
### Note on history
|
||||
|
||||
Any clone taken before 2026-08-08 has a different history and should be
|
||||
discarded rather than merged.
|
||||
@@ -1,99 +0,0 @@
|
||||
# CLAUDE.md — Outer Wilds SK Translation Mod
|
||||
|
||||
Working context for Claude Code (and human contributors) in this repository.
|
||||
|
||||
## What this repo is
|
||||
|
||||
An **unofficial Slovak (slovenčina) translation mod for *Outer Wilds*** — base
|
||||
game **and** the *Echoes of the Eye* DLC. It is primarily a **data/translation
|
||||
project**, not a conventional codebase: the bulk of the work is one large XML file
|
||||
of translated strings, wrapped in a thin C# mod shell.
|
||||
|
||||
- **Not affiliated with Mobius Digital / Annapurna.** Game text is © Mobius
|
||||
Digital, used under their Fan Content Policy. This project's own code and
|
||||
translation are MIT (see [`LICENSE`](LICENSE) and [`README.md`](README.md)).
|
||||
- Roadmap and phase status live in [`PLAN.md`](PLAN.md). Update it as phases land.
|
||||
|
||||
## How the mod works
|
||||
|
||||
It is an [OWML](https://github.com/ow-mods/owml) mod that depends on **xen-42's
|
||||
Localization Utility / Interplanetary Polyglot** (`xen.LocalizationUtility`, MIT).
|
||||
The utility does all the heavy lifting; this mod just:
|
||||
|
||||
1. Declares the dependency in `manifest.json`:
|
||||
`"dependencies": ["xen.LocalizationUtility"]`.
|
||||
2. In its `ModBehaviour.Start()`, grabs the API and registers a new language:
|
||||
```csharp
|
||||
var api = ModHelper.Interaction.TryGetModApi<ILocalizationAPI>("xen.LocalizationUtility");
|
||||
api.RegisterLanguage(this, "Slovenčina", "assets/Translation.xml");
|
||||
```
|
||||
3. Ships the translated strings in `assets/Translation.xml`.
|
||||
|
||||
**No game files are needed to build the mod.** The English source
|
||||
`Translation.xml` is published by the utility repo and used as the template.
|
||||
|
||||
Slovak is a Latin-script language, so **no `AddLanguageFixer`** (that's for RTL
|
||||
scripts) is needed. A custom font via `AddLanguageFont` (Unity **2019.4.27f1**
|
||||
asset bundle) is only required if the stock game font is missing Slovak glyphs —
|
||||
to be verified during in-game testing (Phase 6/7).
|
||||
|
||||
## Planned repo layout
|
||||
|
||||
```
|
||||
Outer-Wilds-SK-Translation-Mod/
|
||||
├── manifest.json # OWML manifest (uniqueName, deps, entry DLL)
|
||||
├── SlovakTranslation.cs # ModBehaviour: registers the language
|
||||
├── ILocalizationAPI.cs # interface copied from the utility
|
||||
├── SlovakTranslation.csproj # build against OWML/game refs
|
||||
├── SlovakTranslation.sln
|
||||
├── assets/
|
||||
│ └── Translation.xml # THE translation (English keys, Slovak values)
|
||||
├── docs/
|
||||
│ └── glossary.md # fixed SK terms for proper nouns
|
||||
├── README.md · CLAUDE.md · PLAN.md · LICENSE
|
||||
```
|
||||
|
||||
Model the C#/manifest scaffold on the community Czech mod
|
||||
([`shippy/outer-wilds-czech`](https://github.com/shippy/outer-wilds-czech)).
|
||||
|
||||
## Translation conventions (important)
|
||||
|
||||
`Translation.xml` is a **flat** `<TranslationTable_XML>` of repeated `<entry>`
|
||||
blocks, each with a `<key>` and a `<value>`. Rules:
|
||||
|
||||
- **Never edit `<key>`.** It is the exact English source string the game matches
|
||||
on — changing it silently breaks that string's translation.
|
||||
- **Translate only `<value>`.** Start from a copy of the English file (key == value)
|
||||
and replace each value with Slovak.
|
||||
- **Preserve inline markup verbatim**, including XML-escaped tags:
|
||||
`<color=orange>…</color>`, `<i>…</i>`, `</color>`,
|
||||
and raw entities `< > &`. Translate the words, keep the tags.
|
||||
- **Keep speaker prefixes** (e.g. `POKE:`, `CLARY:`) and any leading labels.
|
||||
- **Use the glossary** (`docs/glossary.md`) for proper nouns and recurring terms so
|
||||
Nomai / the Eye / Ash Twin Project / etc. render identically everywhere.
|
||||
- Watch text length: Nomai text walls and UI have limited space — prefer concise
|
||||
phrasings where the English is terse.
|
||||
|
||||
**Translation production:** machine-assisted first pass (clean-room, no third-party
|
||||
text) followed by a Slovak-speaking review pass. Phase by category for shippable
|
||||
increments: **UI/menus → dialogue/text walls → ship log**.
|
||||
|
||||
## Build & test
|
||||
|
||||
- Toolchain present locally: `dotnet 6.0.400`, `git`. **The game and the Outer
|
||||
Wilds Mod Manager are NOT installed on this machine** — in-game testing (Phase 7)
|
||||
requires installing *Outer Wilds* + Mod Manager + OWML first.
|
||||
- Build: `dotnet build` (the `.csproj` references OWML/game DLLs — see the Czech
|
||||
mod for the exact reference setup).
|
||||
- Test: load via the Mod Manager, select **Slovenčina**, and verify menus,
|
||||
dialogue, and the ship log render correctly (including diacritics
|
||||
á ä č ď é í ĺ ľ ň ó ô ŕ š ť ú ý ž).
|
||||
|
||||
## Repo / process notes
|
||||
|
||||
- This is a **standalone project repo** (Gitea `Homer/Outer-Wilds-SK-Translation-Mod`),
|
||||
independent of `~/Agent/Systems`. Changes here do **not** require a system
|
||||
changelog entry — unless we install system tooling (game, Mod Manager, a Unity
|
||||
version) to support it, in which case record that in `~/Agent` docs as usual.
|
||||
- Commit as the Gitea identity (Homer <admin@ecoposta.sk>). Don't commit/push
|
||||
unless asked.
|
||||
@@ -1,304 +0,0 @@
|
||||
# PLAN.md — Slovak translation of Outer Wilds
|
||||
|
||||
Roadmap for building the mod. Status markers: ✅ done · 🚧 in progress · ⬜ todo.
|
||||
|
||||
## Goal
|
||||
|
||||
Add **Slovenčina** as a fully selectable language to *Outer Wilds*, covering the
|
||||
**base game and the *Echoes of the Eye* DLC**, distributed as an Outer Wilds Mod
|
||||
Manager mod. Quality target: natural, consistent Slovak — not literal machine
|
||||
output.
|
||||
|
||||
## Approach
|
||||
|
||||
- Built on **xen-42's Localization Utility / Interplanetary Polyglot**
|
||||
(`xen.LocalizationUtility`) — register a new language from one `Translation.xml`.
|
||||
No game files needed to build.
|
||||
- **Translation:** machine-assisted first pass (clean-room, no third-party
|
||||
translation text reused), then a **Slovak-speaking human review pass**. Phased by
|
||||
category so partial releases are usable: **UI/menus → dialogue/text walls →
|
||||
ship log**.
|
||||
- **Scope:** the single ~896 KB `Translation.xml` already contains base game + DLC
|
||||
strings together, so scope is "everything," sequenced internally by category.
|
||||
|
||||
## Phases
|
||||
|
||||
### Phase 1 — Repo scaffold & docs ✅
|
||||
`README.md`, `CLAUDE.md`, `PLAN.md`, and MIT `LICENSE` in place.
|
||||
|
||||
### Phase 2 — Mod skeleton ✅
|
||||
Created the OWML mod shell, modelled on
|
||||
[`shippy/outer-wilds-czech`](https://github.com/shippy/outer-wilds-czech):
|
||||
|
||||
- `manifest.json` — `author: Homer`, `uniqueName: Homer.SlovakTranslation`,
|
||||
`name`, `version`, `owmlVersion`, `dependencies: ["xen.LocalizationUtility"]`.
|
||||
- `ILocalizationAPI.cs` — interface copied from the utility.
|
||||
- `SlovakTranslation.cs` — `ModBehaviour` calling
|
||||
`api.RegisterLanguage(this, "Slovenčina", "assets/Translation.xml")`.
|
||||
- `SlovakTranslation.csproj` / `.sln`, `.gitignore`, empty `assets/`.
|
||||
- Optional: GitHub/Gitea release workflow.
|
||||
|
||||
### Phase 3 — Import English source ✅
|
||||
Imported the base English `Translation.xml` (896 KB, 2424 entries, keys == values)
|
||||
from the utility repo into `assets/`. This is the file to translate.
|
||||
|
||||
> Build verified: `dotnet build -c Release` compiles against the `OWML` /
|
||||
> `OuterWildsGameLibs` NuGet packages (no game install needed) and stages a
|
||||
> loadable mod folder (`SlovakTranslation.dll` + `manifest.json` +
|
||||
> `default-config.json` + `assets/Translation.xml`) in `bin/`.
|
||||
|
||||
### Phase 4 — Glossary 🚧
|
||||
First draft of `docs/glossary.md` in place: tone/register locked (informal *ty*),
|
||||
and SK renderings proposed for the proper nouns and recurring terms below. Rows
|
||||
marked `❓ review` still need the Slovak-speaking review pass to finalize.
|
||||
|
||||
Write `docs/glossary.md` fixing SK renderings (or keep-in-English decisions) for
|
||||
proper nouns and recurring terms, e.g.: Nomai, Hearthian, the Eye / Eye of the
|
||||
Universe, Ash Twin Project, Vessel, Black Hole Forge, Quantum Moon, Sun Station,
|
||||
ship log, Nomai statue, Ember Twin, Ash Twin, Timber Hearth, Brittle Hollow,
|
||||
Giant's Deep, Dark Bramble, Interloper, Stranger (DLC), Owlk/"Owlks" (DLC).
|
||||
Decide tone/register (informal *ty* vs. formal) and lock it here.
|
||||
|
||||
### Phase 5 — Translate `<value>` entries ✅ (machine-assisted pass complete; human review pending)
|
||||
Machine-assisted pass → human review, by category (UI/menus → dialogue → ship log),
|
||||
base + DLC. Preserve all `<color=…>`/`<i>` markup, entities, and speaker
|
||||
prefixes. Track progress and any hard-to-translate lines here or in issues.
|
||||
|
||||
**All three categories now have a complete first-pass translation** (UI 814,
|
||||
ship log 483, dialogue 2423). Whole-file English-leak scan: 0. Remaining work is
|
||||
the **Slovak-speaking human review pass** (puns, register, Nomai text-wall length,
|
||||
the review-flagged lines noted per batch).
|
||||
|
||||
Progress by category (source has 3 sections — the flat `<entry>` list = dialogue/
|
||||
text walls, `<table_shipLog>` = ship log, `<table_ui>` = UI/menus):
|
||||
|
||||
- **UI/menus (`<table_ui>`, 814 entries) — ✅ machine-assisted first pass done,
|
||||
place-name terms reviewed & locked.** All values translated; integer `<key>`
|
||||
IDs untouched; `\n`, `<!>` input-prompt tokens, `<Profile Name>`
|
||||
placeholder, and color/italic markup preserved; XML re-verified well-formed.
|
||||
Casing mirrors the source (ALL-CAPS button labels stay caps). A consistency
|
||||
re-pass applied the locked glossary terms (Scout → *Skaut*, Signalscope →
|
||||
*Signáloskop*, Timber Hearth → *Drevený kozub*, Ash/Ember Twin → *Dvojča
|
||||
Popolu / Dvojča Uhlíka*, etc.). Remaining: a general Slovak review of the
|
||||
non-proper-noun phrasings.
|
||||
- **Ship log (`<table_shipLog>`, 483 entries) — ✅ machine-assisted first pass done.**
|
||||
All values translated (location names + rumor/fact entries); string `<key>`
|
||||
lookups untouched; plain text (no markup). Narrator voice locked to masculine;
|
||||
ship-log place names locked in the glossary (§3, §5b). XML re-verified
|
||||
well-formed; mod builds. **Still needs the Slovak review pass.**
|
||||
- **Dialogue / text walls (flat `<entry>` list, 2423 entries) — ✅ COMPLETE.**
|
||||
Every `<value>` is translated; the only remaining `value==key` entries are
|
||||
proper names (kept in English), the panic-scream onomatopoeia, sick-noises,
|
||||
Kickstarter backer credits, and the ASCII-art easter eggs — all intentional.
|
||||
A whole-file English-leak heuristic (English function-words present, no Slovak
|
||||
diacritics/markers) reports **0** leaks in the flat list, ship log, and UI.
|
||||
Batched by **content type** (not planet — the flat list is asset-ID ordered):
|
||||
Nomai lore/wall-text (by speaker) → Hearthian villagers → travelers →
|
||||
player/system/DLC. Preserve `<color=…>`/`<i>`/`<size=…>` markup,
|
||||
template tokens (`<Pause/>`, `<TimeMinutes>`, `<NbTimeloops>`,
|
||||
`<…SinceRedGiant>`), `\n`, speaker prefixes, and per-entry whitespace.
|
||||
- **Batch 1 — Solanum (70 lines) ✅** — Quantum Moon pilgrim: astronomy-museum
|
||||
walls, Tower of Quantum Knowledge / Quantum Shrine, Eye philosophy. Feminine
|
||||
voice. Applied by key; XML re-verified; builds.
|
||||
- **Batch 2 — Vessel / warp-core debate (29 lines) ✅** — the Nomai clan
|
||||
debating how to obtain the advanced warp core for the Ash Twin Project
|
||||
(Oeno, Clary, Poke, Idaea, Avens, Cassava, Spire, Mitis) + Poke's personal
|
||||
reflections + the Vessel's escape-pod launch / crash computer log. Poke &
|
||||
Clary feminine, Annona masculine.
|
||||
- **Batch 3 — Orbital Probe Cannon (50 lines) ✅** — Construction Yard cyclones
|
||||
(Conoy, Spire, Cassava), building/firing the cannon (Cassava, Daz, Mallow,
|
||||
Privet, Avens, Yarrow), the "let's send a probe" decision, and the cannon's
|
||||
damage-report / launch-log system text. Avens masc, Ramie fem. Preserved
|
||||
`<TimeMinutes>`/`<TimeSeconds>` tokens and the "on the other
|
||||
appendage" Nomai joke.
|
||||
- **Batch 4 — Ash Twin Project warp mechanism (53 lines) ✅** — warp-tower
|
||||
alignment lore, White Hole Station tutorial, tower designs, ore/shell
|
||||
construction, warp-core-source debate (Yarrow, Clary, Poke, Root, Phlox,
|
||||
Oeno, Cycad, Annona, Ramie, Ilex). Pye fem, Plume masc. (Sun Station debate,
|
||||
firing, failure + memory statues still to come.)
|
||||
- **Batch 5 — Sun Station + memory statues (61 lines) ✅** — the Sun Station
|
||||
build debate (Idaea/Pye/Ramie/Poke), Pye's supernova/"gas" humor, the firing
|
||||
orders, the failure aftermath, and the memory statues + masks (Phlox, Daz,
|
||||
Yarrow, Ramie, Oeno, Root). Idaea masc. Preserved the 1304 countdown tokens
|
||||
(`<RemainingMinutes>`…) + `\n` and `<TimeMinutes>`/`<TimeSeconds>`.
|
||||
- **Batch 6 — High Energy Lab (42 lines) ✅** — the negative-time-interval
|
||||
experiments (Pye & Ramie), the white/black-hole-core setup, the 22-minute
|
||||
hypothesis, and the High Energy Lab / Sunless City labels + distance markers.
|
||||
Kept Pye/Ramie's "gas / aeriform" state-of-matter puns (flagged for review)
|
||||
and Conoy's "lose his head" joke.
|
||||
- **Batch 7 — Quantum caves (48 lines) ✅** — the quantum shard, the Quantum
|
||||
Moon locator, the wandering-rock / quantum-travel experiments, Coleus's
|
||||
disappearance and the search for him, and the Ember Twin shelter-path
|
||||
directions (Coleus, Melorae, Bur, Annona, Thatch, Plume). Coleus/Melorae
|
||||
masc. Kept the pre-discovery moon names (*putujúci / prízračný mesiac*) and
|
||||
Melorae's "my sedimentary friend" geologist humor.
|
||||
- **Batch 8 — Interloper shuttle + warp-tower scroll-wall (43 lines) ✅** — the
|
||||
comet crew discovering the exotic/ghost matter in the ruptured stone (Pye,
|
||||
Poke, Clary — all feminine; Poke & Clary are sisters), plus the leftover
|
||||
White Hole Station / warp-tower scroll-wall lines that finish the batch-4
|
||||
conversations (Clary/Poke/Root/Yarrow, incl. the Clary–Yarrow romance).
|
||||
- **Batch 9 — Brittle Hollow / Escape Pod 1 clan saga (94 lines) ✅** — the
|
||||
crash, the volcanic-moon danger, quantum-grove wandering trees/shard, the
|
||||
Eye-signal locator, the migration to the northern glacier, and the loss of
|
||||
loved ones (Plume, Thatch, Filix, Lami, Annona, Rhus, Ilex, Spire, Coleus,
|
||||
Cassava, Kousa). Filix & Melorae revealed **feminine** ("her note", "Aunt
|
||||
Melorae") — corrected batch 7's Melorae lines to feminine here.
|
||||
- **Batch 11 — final Nomai batch (113 lines) ✅ — ALL NOMAI DIALOGUE DONE.**
|
||||
The warp-window details, mining-sites/native-life (Coleus/Cycad/Oeno), the
|
||||
new-Vessel debate (Ilex), the memory-statue philosophy (Phlox/Daz/Cassava),
|
||||
the probe-cannon-origin / Eye-search debate (Avens/Cassava/Plume), the
|
||||
Sun Station "mission" humor (Idaea), the anglerfish-fossil study
|
||||
(Melorae/Coleus), and scattered scroll-wall leftovers. Privet revealed
|
||||
**feminine** ("her brother") — corrected her one masculine line in batch 3.
|
||||
**Every speaker-prefixed Nomai line is now translated.**
|
||||
- **Batch 10 — Bells scrolls + kids' game + Escall's clan history (87 lines) ✅**
|
||||
— the Tower of Quantum Knowledge pilgrimage scrolls (Bells), the Fossil Fish
|
||||
Cave anglerfish blindfold game (Laevi/Taget/Ilex/Lami), and the ancient
|
||||
"Disappearance of Escall" myth + Escape Pod 3 / Secca–Din (Canna, Bromi,
|
||||
Clem, Hyssop, Neem, Escall, Filix, Din). Distant place names translated
|
||||
(*Súmračná galaxia*, *Čierna skala*, *Jasná iskra*) and flagged.
|
||||
- **Nomai dialogue: ✅ complete.** Remaining dialogue is the ~1725
|
||||
Hearthian/player lines (villagers, the travelers, player-facing/system text).
|
||||
- **Hearthian villagers — 🚧 started.**
|
||||
- **Batch 12 — Museum + Slate (100 lines) ✅** — the museum signs/exhibits
|
||||
and Slate the shipbuilder's whole launch-day conversation (ship, launch
|
||||
codes, ship-log markers, marshmallows, his jabs). First use of **mláďa**
|
||||
(Hatchling). Player addressed as *ty*; "Stars above" → *Hviezdy nad nami*;
|
||||
Hearthian names kept (Slate, Hornfels, Gossan, Hal, Mica).
|
||||
- **Batch 13 — Hal + Gossan + Hornfels (204 lines) ✅** — the rest of launch
|
||||
day: Hal (translator inventor, the new Nomai statue), Gossan (flight coach,
|
||||
zero-g training), and Hornfels (curator, launch codes, the travelers'
|
||||
whereabouts, Feldspar, and his redshift "Observations" exhibit on the
|
||||
expanding universe). "Stars above" → *Hviezdy nad nami*; translator tool →
|
||||
*prekladač*; preserved `<Pause>`/`<Pause/>`/`<color=grey>` and `\n\n`.
|
||||
The village kids (Tephra, Galena, Marl, Rutile…) and other NPCs remain.
|
||||
- **⚠️ Scope correction (batch 17):** the earlier line-counts under-counted.
|
||||
A proper scan (a value is untranslated iff it's a suffix of its ID-prefixed
|
||||
key — e.g. key `MeetGabbro3F…` / value `…`) shows **~1090 dialogue lines
|
||||
still untranslated**, not the ~730 previously estimated. Remaining blocks
|
||||
(asset-ID ranges): player-self/duplicate convo (169–308, 140), **Gabbro
|
||||
366–575 ✅**, Feldspar/Chert HUD signs (800–842, 1329–1380, 1822–1840),
|
||||
village kids (1459–1752, ~260), Chert campsite (1975–2283, 308), Signalscope
|
||||
kid + misc (2360–2421, 59), plus generic traveler responses interleaved.
|
||||
- **The travelers — 🚧 started** (Gabbro, Riebeck, Feldspar, Esker, Chert; each a
|
||||
big campsite conversation).
|
||||
- **Batch 17 — Gabbro (204 lines) ✅** — the laid-back "time buddy" on
|
||||
Giant's Deep (*Obrova hlbina*): his surfer-philosopher patter about the
|
||||
time loop, the memory statues, Statue Island (*Ostrov sôch*, his coinage),
|
||||
the Orbital Probe Cannon breaking, his quantum poem/art, the meditation
|
||||
mini-lesson, and the deep-space-satellite ("Ol' Spacey" → **Vesmírko**)
|
||||
inspection log. Masculine; player as *ty*; Hornfels masculine (per existing
|
||||
SK). Preserved `<i>`/`<Pause>` markup and the many repeated
|
||||
menu blocks. **Flag for review:** the "Ol'"-is-affectionate line (465)
|
||||
references old-ness while the nickname *Vesmírko* carries affection via
|
||||
diminutive instead — minor disconnect. Remaining travelers: Chert (308),
|
||||
Esker, Riebeck/Feldspar leftovers.
|
||||
- **Player / self dialogue — 🚧 started.**
|
||||
- **Batch 18 — the "two of you" black-hole duplicate convo (125 lines) ✅**
|
||||
— the meeting between the two copies of the player created by the
|
||||
black-hole/white-hole jump (Ash Twin Project): the confused-memories
|
||||
banter, the dating jokes (Gossan/Slate, "Gossan's eye"), the "are you a
|
||||
figment of my imagination" bit, the *"we are the Feldspar of weird time
|
||||
stuff"* line, the panic-attack screaming sequence, and the post-intro
|
||||
bragging menu (first solo trip, Sun-Station landing, "even Riebeck
|
||||
survived their first launch"). Both speakers are the player → **masculine**;
|
||||
they address each other as *ty*. The 15 pure-scream onomatopoeia lines
|
||||
(AAAH, with `<b>`/`<size=50>` markup) left verbatim as
|
||||
language-neutral. Preserved `<i>`/`<b>`/`<Pause/>`/`<pause>`
|
||||
markup and `\\n\\n`.
|
||||
- **Final dialogue sweep (batches 19–22) — ✅ done in parallel (subagents +
|
||||
main), 770 + 22 lines.** The rest of the flat list, produced by three
|
||||
translator subagents (each writing a JSON of translations, applied
|
||||
race-free in the main thread) plus a large main-thread block:
|
||||
- **Batch 19 — Hearthian village kids / villagers (271 lines) ✅** — Marl,
|
||||
Tephra, Galena, Rutile, Tuff (the sick miner), Spinel, Arkose, Gneiss,
|
||||
Porphy (sap-wine maker), Mica, the model-rocket kid, hide-and-seek, mayor
|
||||
Rutile, the ghost-matter kids. Player as *mláďa*; casual kid register.
|
||||
- **Batch 20 — Chert + Esker + Feldspar's jellyfish journal + Gabbro extras
|
||||
(359 lines) ✅** — Chert the jittery astronomer on the *Presýpacie
|
||||
dvojčatá* (star charts, supernovae, his end-of-universe breakdown, the
|
||||
stargazing campfire finale), **Esker**'s lonely *Mesačná základňa* on the
|
||||
*Skalka*, Feldspar's jellyfish tasting notes, and Gabbro's statue/"I died"
|
||||
variant conversations + band-reunion ending. Also the Ember-Twin research
|
||||
signs, Esker's Signáloskop log, and Gneiss the instrument-maker.
|
||||
- **Batch 21 — signs, Signalscope kid, endgame + Nomai-writing signs (138
|
||||
lines) ✅** — Giant's-Deep HUD/observation signs, the Signalscope-kid
|
||||
endgame scene, the credits/epitaph signs (backer names kept), and the
|
||||
museum Nomai-writing exhibit signs. ASCII-art easter eggs left as art
|
||||
(only embedded words like LOADING→*NAČÍTAVA SA* translated).
|
||||
- **Batch 22 — straggler sweep + consistency (22 lines) ✅** — a whole-file
|
||||
English-heuristic scan caught 22 lines the *suffix-of-key* detector missed
|
||||
(curly-vs-straight-quote drift between key and value: Gabbro "bright flash"
|
||||
variants, the sap-wine labels, the ghost-matter kids' Signáloskop game, two
|
||||
museum signs, the ATP **masks data-readout** at idx 1964, Tektite's scout
|
||||
note). **Detection lesson:** "value is a suffix of its ID-prefixed key" is
|
||||
necessary but not sufficient — always follow up with an English-word / no-
|
||||
Slovak-diacritic heuristic to catch copied-but-drifted values.
|
||||
- **Consistency fixes this pass:** Hollow's Lantern → **Lampáš** (not
|
||||
*Dutinin lampáš*; glossary note added), ghost matter → **prízračná hmota**
|
||||
(was one *duchová hmota*), Hanging City → **Visuté mesto** (was *Visiace*).
|
||||
- **Toolchain:** installed `dotnet-sdk` (10.0.110) locally; `dotnet build -c
|
||||
Release` now **succeeds** (0 warnings/errors) and stages the loadable mod
|
||||
folder in `bin/Release/` (DLL + manifest + config + assets/Translation.xml).
|
||||
- **Batch 14 — Feldspar (120 lines) ✅** — the boastful crashed ace in Dark
|
||||
Bramble (his crash tale, the anglerfish skeleton camp, the "space is
|
||||
bigger inside the seeds" theory). Masculine; heavy on *mláďa*; kept his
|
||||
swagger. Remaining travelers: Gabbro (~213), Riebeck (~125), Chert (~150),
|
||||
Esker (~160).
|
||||
- **Batch 15 — Riebeck (69 lines) ✅** — the anxious, stammering archaeologist
|
||||
on Brittle Hollow: loves the Nomai ruins (the Hanging City), terrified of
|
||||
the "you-know-what" (black hole). Masculine; timid *ehm/uf* voice; kept the
|
||||
`<size=20>` shrinking-text asides. (His planet's HUD labels + the museum
|
||||
star/skeleton exhibits interleaved in this range are deferred to their own
|
||||
batches.) Remaining travelers: Gabbro (~213), Chert (~150), Esker (~160).
|
||||
- **Batch 16 — Nomai shrines + system/HUD text & location signs (98 lines) ✅**
|
||||
— a sweep of the player-facing/system and Nomai-shrine text interleaved
|
||||
through the flat list that earlier speaker-based batches skipped: the
|
||||
**Eye Shrine** and **Quantum Shrine** wall-text (the *Oko vesmíru* signal
|
||||
philosophy Q&A), the **Tower of Quantum Knowledge** trial/pilgrimage lines
|
||||
("Seek the wandering arch", quantum-imaging congratulations), the Brittle
|
||||
Hollow **location signs** (districts + directional `\\n(sever/juh/… N m)`
|
||||
markers — *Visuté mesto*, *Kováreň čiernych dier*, *Veža kvantového
|
||||
poznania*, etc.), the **Escape Pod 2/3 flightlogs** + cannon/probe/Sun-tower
|
||||
system readouts (`<NbTimeloops>`, `<TimeMinutes>`,
|
||||
`<MinutesSinceRedGiant>` tokens preserved), and scattered UI labels
|
||||
(RECORDING → *NAHRÁVANIE*, warnings/verdicts, "the Prisoner" → *Väzeň*).
|
||||
Directions localized (north→sever, below→dole, left→vľavo…); "281,042" →
|
||||
*281 042*. Left the two ASCII-art easter eggs (LOADING/QR) unchanged. XML
|
||||
re-verified well-formed. **Only remaining key==value entries are the 22
|
||||
Hearthian/Nomai character names (kept in English) + those 2 art blocks.**
|
||||
|
||||
Terminology change (applied file-wide): **Black Hole Forge → Kováreň čiernych
|
||||
dier** (was *Zlieváreň čiernej diery*) — 15 occurrences across ship log + dialogue.
|
||||
|
||||
### Phase 6 — Diacritic / font check ⬜
|
||||
Verify the stock game font renders all Slovak glyphs
|
||||
(á ä č ď é í ĺ ľ ň ó ô ŕ š ť ú ý ž). Only if any are missing: build a font asset
|
||||
bundle in **Unity 2019.4.27f1** and wire `api.AddLanguageFont(...)`.
|
||||
|
||||
### Phase 7 — Build & in-game test ⬜
|
||||
**Prerequisite:** install *Outer Wilds* + Outer Wilds Mod Manager + OWML (none are
|
||||
on this machine yet). Then `dotnet build`, load via the Mod Manager, select
|
||||
Slovenčina, and verify menus, dialogue, and ship log render correctly.
|
||||
|
||||
### Phase 8 — Release ⬜
|
||||
Tag a Gitea release; optionally submit to the Outer Wilds mod database so the mod
|
||||
appears in the Mod Manager for everyone.
|
||||
|
||||
## Open items / risks
|
||||
|
||||
- **Font coverage** for Slovak-specific glyphs (ľ ĺ ŕ ô ä) is unverified until
|
||||
in-game testing (Phase 6/7).
|
||||
- **Translation volume is the real cost** — ~896 KB of source text. A
|
||||
Slovak-speaking review pass is essential, especially for DLC/dialogue nuance,
|
||||
puns, and Nomai text-wall length constraints.
|
||||
- **In-game testing is blocked** until the game + Mod Manager are installed locally.
|
||||
- Confirm the tone/register decision (Phase 4) early — reworking it later is costly.
|
||||
|
||||
## References
|
||||
|
||||
- Localization Utility / Interplanetary Polyglot (framework, MIT, source template):
|
||||
https://github.com/xen-42/outer-wilds-localization-utility
|
||||
- Czech mod (structure reference): https://github.com/shippy/outer-wilds-czech
|
||||
- OWML: https://github.com/ow-mods/owml
|
||||
- Mod Manager: https://outerwildsmods.com/mod-manager/
|
||||
@@ -7,7 +7,7 @@
|
||||
> the base game and the Echoes of the Eye DLC.*
|
||||
|
||||
**Stav / Status:** 🚧 **Work in progress** — the mod scaffold and translation are
|
||||
being built. See [`PLAN.md`](PLAN.md) for the roadmap.
|
||||
being built. See the [Roadmap](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki/Roadmap).
|
||||
|
||||
Outer Wilds officially ships in 12 languages; Slovak is not one of them. This mod
|
||||
adds it as a new selectable language using the community localization framework —
|
||||
@@ -34,7 +34,7 @@ at runtime.
|
||||
mod lets you switch language in-game with `Ctrl+L`.
|
||||
|
||||
> Until the first release is published, the mod is not yet in the Mod Manager
|
||||
> database — see [`PLAN.md`](PLAN.md) for how to build it from source.
|
||||
> database — see the [Roadmap](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki/Roadmap) for how to build it from source.
|
||||
|
||||
## Contributing / Prispievanie
|
||||
|
||||
@@ -45,21 +45,24 @@ Translation fixes are very welcome — the goal is natural, consistent Slovak.
|
||||
**Never change the `<key>`** — it is the English identifier the game matches on.
|
||||
- Preserve all inline formatting exactly, e.g. `<color=orange>…</color>`,
|
||||
`<i>`, and speaker prefixes like `POKE:`.
|
||||
- Follow the terminology in `docs/glossary.md` so names (Nomai, the Eye, Ash Twin
|
||||
- Follow the terminology in the [Glossary](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki/Glossary) so names (Nomai, the Eye, Ash Twin
|
||||
Project, …) stay consistent across the whole game.
|
||||
|
||||
See [`CLAUDE.md`](CLAUDE.md) for the full conventions and repo layout.
|
||||
See the [Working notes](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki/Working-notes) for the full conventions and repo layout.
|
||||
|
||||
## License & disclaimer
|
||||
|
||||
The **original mod code and the Slovak translation** in this repository are
|
||||
released under the [MIT License](LICENSE).
|
||||
|
||||
The bundled UI font in `assets/slovakfont` is **[Cabin](https://github.com/impallari/Cabin)**
|
||||
by the Cabin Project Authors, used under the **SIL Open Font License 1.1**
|
||||
(see [`assets/Cabin-OFL.txt`](assets/Cabin-OFL.txt)). It is only used for the few
|
||||
menu/HUD elements whose stock font was never baked with Slovak caron glyphs — see
|
||||
[`SlovakFont.cs`](SlovakFont.cs).
|
||||
The bundled fallback font in `assets/slovakfont` is
|
||||
**[Cabin](https://github.com/impallari/Cabin)** by the Cabin Project Authors, used
|
||||
under the **SIL Open Font License 1.1** (see
|
||||
[`assets/Cabin-OFL.txt`](assets/Cabin-OFL.txt)). The game's own menu and HUD fonts
|
||||
were never baked with Slovak caron glyphs, so those labels are redrawn with a font
|
||||
that has them — preferably one of the game's own dynamic fonts, and Cabin only where
|
||||
it ships none. See [`SlovakFont.cs`](SlovakFont.cs), and the `preferGameTypeface`
|
||||
setting if you would rather have Cabin everywhere.
|
||||
|
||||
This is an **unofficial** fan project. It is **not affiliated with, approved by, or
|
||||
endorsed by Mobius Digital or Annapurna Interactive.** *Outer Wilds*, its story,
|
||||
|
||||
+221
-111
@@ -1,9 +1,8 @@
|
||||
using HarmonyLib;
|
||||
using OWML.Common;
|
||||
using OWML.ModHelper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
@@ -15,36 +14,70 @@ namespace SlovakTranslation
|
||||
/// Outer Wilds renders Latin languages with a handful of *static* font atlases,
|
||||
/// and only some of them were baked with Latin Extended-A:
|
||||
///
|
||||
/// Gill Sans MT / Gill Sans MT Menu (menus, prompts) 243 glyphs — no carons
|
||||
/// ParaType - Futura PT Medium (language font) 663 glyphs — complete
|
||||
/// SpaceMono-Regular (translator) 612 glyphs — complete
|
||||
/// Adobe - SerifGothicStd (+ExtraBold) menus 253 glyphs — no carons
|
||||
/// Gill Sans MT (+Menu, Bold) HUD prompts 243 glyphs — no carons
|
||||
/// ParaType - Futura PT Medium dialogue 663 glyphs — complete
|
||||
/// SpaceMono-Regular translator 612 glyphs — complete
|
||||
///
|
||||
/// That is why dialogue and the Nomai translator always looked right while
|
||||
/// "Pokračovať" came out as "Pokra ova". Registering a whole custom language
|
||||
/// font via the Localization Utility fixes the menus but also flips
|
||||
/// <c>TextTranslation.IsLanguageLatin()</c> to false, which drags dialogue,
|
||||
/// the translator and the ship log off their proper fonts too.
|
||||
/// "Pokračovať" came out as "Pokra ova".
|
||||
///
|
||||
/// So instead we leave the language font alone and swap fonts *only* where the
|
||||
/// vanilla one physically cannot draw Slovak — checked at runtime with
|
||||
/// <c>Font.HasCharacter</c>, so we never touch a font that renders fine.
|
||||
/// Registering a whole custom language font via the Localization Utility fixes
|
||||
/// the menus, but it also flips <c>TextTranslation.IsLanguageLatin()</c> to
|
||||
/// false, which drags dialogue, the translator and the ship log off their
|
||||
/// proper fonts. And <c>UIStyleManager.GetMenuFont()</c> — the obvious hook —
|
||||
/// is dead code with no callers; the fonts are assigned straight onto the
|
||||
/// <see cref="Text"/> components in the scenes.
|
||||
///
|
||||
/// So we substitute at the Text level, but the decision is made **per font, not
|
||||
/// per label**: a font that cannot draw Slovak is replaced everywhere it is
|
||||
/// used, so a menu never mixes two typefaces. Fonts that can draw Slovak —
|
||||
/// the dialogue and translator fonts — are left completely alone.
|
||||
///
|
||||
/// The replacement is preferably the game's *own* dynamic cut of the same
|
||||
/// typeface (it ships several, e.g. Adobe - SerifGothicStd_Dynamic), which keeps
|
||||
/// the menu pixel-identical to vanilla. Bundled Cabin is the fallback.
|
||||
/// </summary>
|
||||
internal static class SlovakFont
|
||||
{
|
||||
/// <summary>Cabin (SIL OFL 1.1), a humanist sans close to the vanilla Gill Sans MT.
|
||||
/// Shipped as a dynamic font, so it can draw any glyph Slovak needs.</summary>
|
||||
/// <summary>Cabin (SIL OFL 1.1), a humanist sans in the Gill Sans lineage, used
|
||||
/// where the game has no dynamic cut of its own. Dynamic, so it can draw any
|
||||
/// glyph Slovak needs.</summary>
|
||||
private static Font _font;
|
||||
|
||||
/// <summary>Characters the vanilla menu atlas is missing. If a font can draw all
|
||||
/// of these it is left completely alone.</summary>
|
||||
private static readonly char[] Probe = { 'č', 'ď', 'ĺ', 'ľ', 'ň', 'ŕ', 'ť', 'ž', 'ô', 'ä' };
|
||||
/// <summary>The letters Slovak adds on top of plain ASCII. Only these are worth
|
||||
/// probing — anything else in the text was already fine in English.</summary>
|
||||
private const string SlovakLetters = "áäčďéíĺľňóôŕšťúýžÁÄČĎÉÍĹĽŇÓÔŔŠŤÚÝŽ";
|
||||
|
||||
private static readonly Dictionary<int, bool> _coverage = new Dictionary<int, bool>();
|
||||
/// <summary>Stylised display faces (the ship's readouts, seven-segment digits).
|
||||
/// Replacing these wholesale would cost more in looks than it gains, so they
|
||||
/// are only substituted on the individual labels that actually need a glyph.</summary>
|
||||
private static readonly string[] Stylised = { "VCR_OSD_MONO", "digital-7", "PCBius" };
|
||||
|
||||
/// <summary>Font instance ID → the Slovak letters that font cannot draw.</summary>
|
||||
private static readonly Dictionary<int, string> _gaps = new Dictionary<int, string>();
|
||||
|
||||
/// <summary>Labels we substituted, and the font the game wanted on them.</summary>
|
||||
private static readonly Dictionary<Text, Font> _swapped = new Dictionary<Text, Font>();
|
||||
|
||||
/// <summary>Original font instance ID → what we put in its place.</summary>
|
||||
private static readonly Dictionary<int, Font> _substitutes = new Dictionary<int, Font>();
|
||||
|
||||
/// <summary>The game's own dynamic fonts, which can draw glyphs their static
|
||||
/// siblings were never baked with.</summary>
|
||||
private static Font[] _gameDynamicFonts = new Font[0];
|
||||
|
||||
/// <summary>When set, a static font is replaced by the game's own dynamic cut of the
|
||||
/// same typeface where one exists, keeping the vanilla look. Cabin otherwise.</summary>
|
||||
internal static bool PreferGameTypeface = true;
|
||||
|
||||
private static ModBehaviour _mod;
|
||||
|
||||
internal static bool Loaded => _font != null;
|
||||
|
||||
internal static void Load(ModBehaviour mod)
|
||||
{
|
||||
_mod = mod;
|
||||
var path = mod.ModHelper.Manifest.ModFolderPath + "assets/slovakfont";
|
||||
var bundle = AssetBundle.LoadFromFile(path);
|
||||
if (bundle == null)
|
||||
@@ -57,7 +90,7 @@ namespace SlovakTranslation
|
||||
{
|
||||
if (font.name != "SlovakUI") continue;
|
||||
_font = font;
|
||||
UnityEngine.Object.DontDestroyOnLoad(font);
|
||||
Object.DontDestroyOnLoad(font);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -65,122 +98,199 @@ namespace SlovakTranslation
|
||||
mod.ModHelper.Console.WriteLine("Font bundle has no 'SlovakUI' font.", MessageType.Error);
|
||||
}
|
||||
|
||||
/// <summary>Returns <paramref name="font"/> unchanged unless Slovenčina is the
|
||||
/// active language and that font cannot draw Slovak.</summary>
|
||||
internal static Font Fix(Font font)
|
||||
/// <summary>Give <paramref name="text"/> a font that can draw Slovak, or hand back
|
||||
/// the game's own font once it is no longer needed.</summary>
|
||||
internal static void Apply(Text text)
|
||||
{
|
||||
if (_font == null || font == null || font == _font) return font;
|
||||
if (_font == null || text == null) return;
|
||||
|
||||
// Dynamic fonts rasterise straight from an embedded font file; every one the
|
||||
// game ships for Latin covers Slovak, and HasCharacter is unreliable for them.
|
||||
if (font.dynamic) return font;
|
||||
var current = text.font;
|
||||
Font stored;
|
||||
var swapped = _swapped.TryGetValue(text, out stored) && stored != null &&
|
||||
current == SubstituteFor(stored);
|
||||
|
||||
if (!IsActive()) return font;
|
||||
// If anything else assigned a font since our swap, that is the new baseline.
|
||||
var wanted = swapped ? stored : current;
|
||||
if (!swapped) _swapped.Remove(text);
|
||||
if (wanted == null) return;
|
||||
|
||||
var needsHelp = NeedsSubstitute(wanted, text.text);
|
||||
if (needsHelp == swapped) return;
|
||||
|
||||
if (needsHelp)
|
||||
{
|
||||
_swapped[text] = wanted;
|
||||
text.font = SubstituteFor(wanted);
|
||||
}
|
||||
else
|
||||
{
|
||||
_swapped.Remove(text);
|
||||
text.font = wanted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>What to draw <paramref name="original"/>'s labels with instead. The
|
||||
/// game ships dynamic cuts of several of its typefaces; borrowing the matching one
|
||||
/// keeps the menu looking exactly like vanilla, which no substitute font can.</summary>
|
||||
private static Font SubstituteFor(Font original)
|
||||
{
|
||||
Font cached;
|
||||
if (_substitutes.TryGetValue(original.GetInstanceID(), out cached) && cached != null) return cached;
|
||||
if (!PreferGameTypeface) return _font;
|
||||
|
||||
if (_gameDynamicFonts.Length == 0) RefreshGameFonts();
|
||||
|
||||
Font best = null;
|
||||
var bestLength = 0;
|
||||
foreach (var candidate in _gameDynamicFonts)
|
||||
{
|
||||
if (candidate == null) continue;
|
||||
var baseName = candidate.name.EndsWith("_Dynamic")
|
||||
? candidate.name.Substring(0, candidate.name.Length - "_Dynamic".Length)
|
||||
: candidate.name;
|
||||
|
||||
if (baseName.Length <= bestLength) continue;
|
||||
if (!original.name.StartsWith(baseName, System.StringComparison.Ordinal)) continue;
|
||||
if (GapsOf(candidate).Length != 0) continue;
|
||||
|
||||
best = candidate;
|
||||
bestLength = baseName.Length;
|
||||
}
|
||||
|
||||
if (best == null) return _font;
|
||||
|
||||
_substitutes[original.GetInstanceID()] = best;
|
||||
_mod?.ModHelper.Console.WriteLine(
|
||||
$"drawing \"{original.name}\" with the game's own \"{best.name}\"", MessageType.Info);
|
||||
return best;
|
||||
}
|
||||
|
||||
private static void RefreshGameFonts()
|
||||
{
|
||||
var found = new List<Font>();
|
||||
foreach (var font in Resources.FindObjectsOfTypeAll<Font>())
|
||||
{
|
||||
if (font != null && font.dynamic && font != _font) found.Add(font);
|
||||
}
|
||||
_gameDynamicFonts = found.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>Drop every cached decision, so a settings change takes effect at once.</summary>
|
||||
internal static void ForgetChoices()
|
||||
{
|
||||
_substitutes.Clear();
|
||||
_gameDynamicFonts = new Font[0];
|
||||
foreach (var pair in _swapped)
|
||||
{
|
||||
if (pair.Key != null && pair.Value != null) pair.Key.font = pair.Value;
|
||||
}
|
||||
_swapped.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Re-check every live label. Scene loads and language changes reassign
|
||||
/// fonts wholesale, and menus are built lazily, so sweep periodically too.</summary>
|
||||
internal static void ApplyToAll()
|
||||
{
|
||||
if (_font == null) return;
|
||||
|
||||
// Labels that have since been destroyed would otherwise pile up.
|
||||
var dead = new List<Text>();
|
||||
foreach (var pair in _swapped)
|
||||
{
|
||||
if (pair.Key == null) dead.Add(pair.Key);
|
||||
}
|
||||
foreach (var text in dead) _swapped.Remove(text);
|
||||
|
||||
RefreshGameFonts();
|
||||
foreach (var text in Object.FindObjectsOfType<Text>()) Apply(text);
|
||||
}
|
||||
|
||||
private static bool NeedsSubstitute(Font font, string content)
|
||||
{
|
||||
if (!CustomLanguageActive()) return false;
|
||||
|
||||
var gaps = GapsOf(font);
|
||||
if (gaps.Length == 0) return false;
|
||||
|
||||
// Ordinary UI faces are replaced everywhere they appear, so a menu never
|
||||
// mixes typefaces. Stylised readouts only give way when a glyph is at stake.
|
||||
if (!IsStylised(font.name)) return true;
|
||||
|
||||
if (string.IsNullOrEmpty(content)) return false;
|
||||
foreach (var c in content)
|
||||
{
|
||||
if (gaps.IndexOf(c) >= 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GapsOf(Font font)
|
||||
{
|
||||
var id = font.GetInstanceID();
|
||||
if (!_coverage.TryGetValue(id, out var complete))
|
||||
string gaps;
|
||||
if (_gaps.TryGetValue(id, out gaps)) return gaps;
|
||||
|
||||
// Dynamic fonts only report a character as present once it has been
|
||||
// rasterised, so ask for the whole Slovak set before probing.
|
||||
if (font.dynamic) font.RequestCharactersInTexture(SlovakLetters);
|
||||
|
||||
var builder = new StringBuilder();
|
||||
foreach (var c in SlovakLetters)
|
||||
{
|
||||
complete = true;
|
||||
foreach (var c in Probe)
|
||||
if (!font.HasCharacter(c)) builder.Append(c);
|
||||
}
|
||||
gaps = builder.ToString();
|
||||
_gaps[id] = gaps;
|
||||
|
||||
if (gaps.Length > 0)
|
||||
{
|
||||
if (font.HasCharacter(c)) continue;
|
||||
complete = false;
|
||||
break;
|
||||
_mod?.ModHelper.Console.WriteLine(
|
||||
$"font \"{font.name}\" cannot draw \"{gaps}\" — " +
|
||||
(IsStylised(font.name) ? "substituting only where needed" : "substituting everywhere"),
|
||||
MessageType.Info);
|
||||
}
|
||||
_coverage[id] = complete;
|
||||
return gaps;
|
||||
}
|
||||
|
||||
return complete ? font : _font;
|
||||
private static bool IsStylised(string fontName)
|
||||
{
|
||||
foreach (var stylised in Stylised)
|
||||
{
|
||||
if (fontName.IndexOf(stylised, System.StringComparison.OrdinalIgnoreCase) >= 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#region "is Slovenčina selected?"
|
||||
|
||||
// The Localization Utility invents a TextTranslation.Language value for each
|
||||
// custom language, so it is not in the enum at compile time. Ask the utility
|
||||
// once, then cache the value and compare enums from then on.
|
||||
private static bool _resolved;
|
||||
private static TextTranslation.Language _slovak;
|
||||
private static MethodInfo _tryGetLanguage;
|
||||
private static object _utility;
|
||||
|
||||
private static bool IsActive()
|
||||
/// <summary>True while a mod-registered language is selected. The Localization
|
||||
/// Utility appends custom languages past <c>Language.TOTAL</c>, and treats
|
||||
/// everything up to it as vanilla — same test it uses itself.</summary>
|
||||
private static bool CustomLanguageActive()
|
||||
{
|
||||
if (TextTranslation.s_theTable == null) return false;
|
||||
|
||||
var current = TextTranslation.Get().GetLanguage();
|
||||
if (_resolved) return current == _slovak;
|
||||
|
||||
if (_utility == null)
|
||||
{
|
||||
var type = SlovakTranslation.LocalizationApi?.GetType().Assembly.GetType("LocalizationUtility.LocalizationUtility");
|
||||
if (type == null) return false;
|
||||
_utility = type.GetField("Instance", BindingFlags.Public | BindingFlags.Static)?.GetValue(null);
|
||||
foreach (var m in type.GetMethods())
|
||||
{
|
||||
var p = m.GetParameters();
|
||||
if (m.Name == "TryGetLanguage" && p.Length == 2 &&
|
||||
p[0].ParameterType == typeof(TextTranslation.Language))
|
||||
{
|
||||
_tryGetLanguage = m;
|
||||
break;
|
||||
return TextTranslation.Get().GetLanguage() > TextTranslation.Language.TOTAL;
|
||||
}
|
||||
}
|
||||
if (_utility == null || _tryGetLanguage == null) return false;
|
||||
}
|
||||
|
||||
var args = new object[] { current, null };
|
||||
if (!(bool)_tryGetLanguage.Invoke(_utility, args) || args[1] == null) return false;
|
||||
|
||||
var name = args[1].GetType().GetProperty("Name")?.GetValue(args[1], null) as string;
|
||||
if (name != SlovakTranslation.LanguageName) return false;
|
||||
|
||||
_slovak = current;
|
||||
_resolved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Every place the game hands out a font that is not the language font. Each one
|
||||
/// runs through <see cref="SlovakFont.Fix"/>, which is a no-op unless the font
|
||||
/// really is missing Slovak glyphs.
|
||||
/// Hooks: every label as it appears or changes, plus a sweep whenever the game
|
||||
/// reassigns fonts wholesale.
|
||||
/// </summary>
|
||||
[HarmonyPatch]
|
||||
internal static class SlovakFontPatches
|
||||
{
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetMenuFont))]
|
||||
public static void MenuFont(ref Font __result) => __result = SlovakFont.Fix(__result);
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(Text), "OnEnable")]
|
||||
public static void TextEnabled(Text __instance) => SlovakFont.Apply(__instance);
|
||||
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetTranslatorFont))]
|
||||
public static void TranslatorFont(ref Font __result) => __result = SlovakFont.Fix(__result);
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(Text), "text", MethodType.Setter)]
|
||||
public static void TextChanged(Text __instance) => SlovakFont.Apply(__instance);
|
||||
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetShipLogFont))]
|
||||
public static void ShipLogFont(ref Font __result) => __result = SlovakFont.Fix(__result);
|
||||
// The game reassigns fonts wholesale when the language changes. Re-deciding here
|
||||
// is safe: our own assignment re-enters once, finds the state already correct,
|
||||
// and stops.
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(Text), "font", MethodType.Setter)]
|
||||
public static void FontAssigned(Text __instance) => SlovakFont.Apply(__instance);
|
||||
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetShipLogCardFont))]
|
||||
public static void ShipLogCardFont(ref Font __result) => __result = SlovakFont.Fix(__result);
|
||||
|
||||
// Prompts ("Podrž", "Pokračovať"…) cache their font in a private field and then
|
||||
// rebuild, so patch after the fact and rebuild once more.
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(PromptManager), "OnLanguageChanged")]
|
||||
public static void PromptFont(PromptManager __instance)
|
||||
{
|
||||
var field = AccessTools.Field(typeof(PromptManager), "_currentFont");
|
||||
var current = field.GetValue(__instance) as Font;
|
||||
var fixedFont = SlovakFont.Fix(current);
|
||||
if (fixedFont == current) return;
|
||||
|
||||
field.SetValue(__instance, fixedFont);
|
||||
AccessTools.Method(typeof(PromptManager), "RebuildUI")?.Invoke(__instance, null);
|
||||
}
|
||||
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(GameOverController), nameof(GameOverController.SetupGameOverScreen))]
|
||||
public static void DeathFont(GameOverController __instance)
|
||||
{
|
||||
var text = AccessTools.Field(typeof(GameOverController), "_deathText").GetValue(__instance) as Text;
|
||||
if (text != null) text.font = SlovakFont.Fix(text.font);
|
||||
}
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(TextTranslation), nameof(TextTranslation.SetLanguage))]
|
||||
public static void LanguageChanged() => SlovakFont.ApplyToAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,25 @@ namespace SlovakTranslation
|
||||
if (SlovakFont.Loaded)
|
||||
{
|
||||
new Harmony("Homer.SlovakTranslation").PatchAll();
|
||||
UnityEngine.SceneManagement.SceneManager.sceneLoaded += (scene, mode) => SlovakFont.ApplyToAll();
|
||||
ModHelper.Console.WriteLine("Slovak menu/HUD font (Cabin) loaded and patched in.", MessageType.Success);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <c>preferGameTypeface</c> — when on, a menu font that can't draw Slovak is
|
||||
/// replaced by the game's own dynamic cut of the same typeface where one exists,
|
||||
/// so the menu keeps its vanilla look. Turn it off to use the bundled Cabin
|
||||
/// everywhere instead.
|
||||
/// </summary>
|
||||
public override void Configure(IModConfig config)
|
||||
{
|
||||
SlovakFont.PreferGameTypeface = config.GetSettingsValue<bool>("preferGameTypeface");
|
||||
if (!SlovakFont.Loaded) return;
|
||||
|
||||
SlovakFont.ForgetChoices();
|
||||
SlovakFont.ApplyToAll();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
+4
-1
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"settings": {
|
||||
"preferGameTypeface": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
# Glossary / Slovník — Outer Wilds SK
|
||||
|
||||
Fixed Slovak renderings for proper nouns and recurring terms, so names stay
|
||||
**identical everywhere** in `assets/Translation.xml`. Follow this file when
|
||||
translating; propose changes here (not ad-hoc in the XML).
|
||||
|
||||
> **Status:** place names & proper nouns reviewed and **locked** (2026-07-20,
|
||||
> the "go risky" pass — planet names are translated, not kept in English). Rows
|
||||
> still marked `❓ review` need the Slovak-speaking review pass before they are
|
||||
> final; `🔒 locked` rows are settled unless there's a strong reason. The UI/menus
|
||||
> translation in `Translation.xml` has been re-passed to match the locked terms.
|
||||
|
||||
---
|
||||
|
||||
## 0. Tone & register (locked)
|
||||
|
||||
- **Address the player informally — *ty*, not *vy*.** Outer Wilds has a warm,
|
||||
around-the-campfire tone; the Hearthians are your friends. Use *ty* / informal
|
||||
imperatives (e.g. *"Pozri sa"*, not *"Pozrite sa"*) throughout menus, prompts,
|
||||
and dialogue.
|
||||
- **UI casing mirrors the source.** The game bakes capitalization into the
|
||||
strings (many buttons are ALL-CAPS in the data), so ALL-CAPS English → ALL-CAPS
|
||||
Slovak; otherwise sentence case. Fixed proper names (Skaut, Signáloskop, Dvojča
|
||||
Popolu, …) keep the capitalization given in this glossary.
|
||||
- **Keep the source's voice per speaker.** Nomai text is formal and precise;
|
||||
Hearthian dialogue is casual. Register can shift by *speaker*, but the
|
||||
player is always addressed as *ty*.
|
||||
- **Diacritics always** — á ä č ď é í ĺ ľ ň ó ô ŕ š ť ú ý ž. Never strip them.
|
||||
- **Narrator gender (locked):** the player-character is canonically genderless, but
|
||||
Slovak past tense forces a gender. Use **masculine** for the player's first-person
|
||||
log/dialogue voice (*Našiel som*, *Videl som*, *Vypustil som*). Named characters
|
||||
take their English gender where given (**Solanum** = feminine; **Coleus** =
|
||||
masculine); the singular-*they* travelers (Riebeck, Feldspar, Gabbro, Esker,
|
||||
Chert) default to **masculine**.
|
||||
|
||||
## 1. General rules
|
||||
|
||||
- **Never edit `<key>`.** Translate only `<value>`. (See `CLAUDE.md`.)
|
||||
- **Preserve inline markup verbatim:** `<color=…>…</color>`,
|
||||
`<i>…</i>`, entities `< > &`. Translate the words, keep
|
||||
the tags and the exact color names (`lightblue`, `orange`, …).
|
||||
- **Keep speaker prefixes verbatim:** `POKE:`, `CLARY:`, `SOLANUM:`, etc. — do
|
||||
not translate or reorder the label.
|
||||
- **Declension:** Slovak inflects. A glossary entry gives the base (nominative)
|
||||
form; decline it naturally in context (*na Drevenom kozube*, *z Temného tŕnia*,
|
||||
*do Krehkej dutiny*). Keep the **stem/spelling** from this table so
|
||||
search-and-replace stays reliable. **Nomai** is the one exception — see below.
|
||||
- **Brand / title names stay in English (verbatim):** the game title **Outer
|
||||
Wilds**, the space program **Outer Wilds Ventures**, and "the Outer Wilds" on
|
||||
the *Planetary Chart* poster. They're the actual named brand in the game (like
|
||||
a company name — you wouldn't translate "SpaceX"). Inflect the *surrounding*
|
||||
Slovak, not the name: *v hre Outer Wilds*, *podporuješ Outer Wilds Ventures*.
|
||||
- **Character names are kept in English** (they're geology terms — Hornfels,
|
||||
Slate, Gabbro, Riebeck, Feldspar, Chert, Esker, Hal, Gossan, Marl, Tuff,
|
||||
Tephra, Galena, Moraine, Rutile, Spinel, Mica, Porphy, Arkose…). Decline
|
||||
where natural: *Gabbrovi*, *s Riebeckom*, *Hala*.
|
||||
|
||||
---
|
||||
|
||||
## 2. Peoples & beings
|
||||
|
||||
| English | Slovak | Status | Notes |
|
||||
|---|---|---|---|
|
||||
| Nomai (species & individual) | **Nomai** | 🔒 | **Indeclinable** — keep spelling *Nomai* in every case (sg. = pl.). It's an alien species name; leave it as-is. |
|
||||
| Hearthian(s) | **Kozubčan** (sg.), **Kozubčania** (pl.) | 🔒 | From *kozub* (→ Drevený kozub). Adj. *kozubčiansky*. |
|
||||
| the Owlks *(DLC, fan term)* | **Soví človek** (sg.), **Soví ľudia** (pl.) | 🔒 | The game never names them; "owl-people". |
|
||||
| Hatchling *(the player; a young Hearthian)* | **mláďa** (neuter) | 🔒 | Affectionate address from other Hearthians *and* a common noun. Neuter → **gender-neutral** (fits the genderless protagonist). Pl. *mláďatá* (*odkedy sme boli mláďatá*); address *"Jasné, mláďa!"*. |
|
||||
|
||||
## 3. Celestial bodies & places
|
||||
|
||||
Decision (locked, "go risky"): **place names are translated**, including the home
|
||||
planet and moons — not kept in English.
|
||||
|
||||
| English | Slovak | Status | Notes |
|
||||
|---|---|---|---|
|
||||
| the Sun | **Slnko** | 🔒 | |
|
||||
| Sun Station | **Slnečná stanica** | 🔒 | |
|
||||
| Timber Hearth (home planet) | **Drevený kozub** | 🔒 | Home planet. Demonym *Kozubčania* derives from *kozub*. |
|
||||
| The Attlerock (moon) | **Skalka** | 🔒 | Diminutive of *skala* — mirrors the "a little rock" pun. |
|
||||
| Brittle Hollow | **Krehká dutina** | 🔒 | |
|
||||
| Hollow's Lantern (moon) | **Lampáš** | 🔒 | Just **Lampáš** — do **not** form a possessive from *Krehká dutina* (never *Dutinin lampáš*). Decline the noun itself: *na Lampáši*, *k Lampášu*. |
|
||||
| Hourglass Twins | **Presýpacie dvojčatá** | 🔒 | Ember + Ash together. |
|
||||
| Ember Twin | **Dvojča Uhlíka** | 🔒 | Matched pair with *Dvojča Popolu* (uhlík ↔ popol). |
|
||||
| Ash Twin | **Dvojča Popolu** | 🔒 | Drives *Projekt Dvojčaťa Popolu* (§4). |
|
||||
| Giant's Deep | **Obrova hlbina** | 🔒 | |
|
||||
| Dark Bramble | **Temné tŕnie** | 🔒 | *bramble* = tŕnie. |
|
||||
| The Interloper (comet) | **Votrelec** | 🔒 | |
|
||||
| Quantum Moon | **Kvantový mesiac** | 🔒 | |
|
||||
| White Hole / Black Hole | **biela diera / čierna diera** | 🔒 | Lowercase (common noun). |
|
||||
| Black Hole Forge | **Kováreň čiernych dier** | 🔒 | Forge/smithy of the black holes. Note the **plural** *čiernych dier*. Decline: gen *Kovárne*, loc *Kovárni*. (Superseded earlier *Zlieváreň čiernej diery*.) |
|
||||
| The Stranger *(DLC)* | **Cudzinec** | 🔒 | |
|
||||
| Echoes of the Eye *(DLC title)* | **Ozveny Oka** | ❓ | Translate in prose; may keep English as a store/product title. |
|
||||
|
||||
## 4. Story, projects & artifacts
|
||||
|
||||
| English | Slovak | Status | Notes |
|
||||
|---|---|---|---|
|
||||
| the Eye of the Universe | **Oko vesmíru** | 🔒 | Short form: **Oko**. Keep any color markup around "Eye". |
|
||||
| the Eye (short) | **Oko** | 🔒 | |
|
||||
| Eye Signal | **signál Oka** | 🔒 | |
|
||||
| Ash Twin Project | **Projekt Dvojčaťa Popolu** | 🔒 | Matches *Dvojča Popolu* (§3). |
|
||||
| the Vessel (Nomai ship) | **Plavidlo** | 🔒 | |
|
||||
| Warp Core | **warpové jadro** | 🔒 | |
|
||||
| Advanced Warp Core | **pokročilé warpové jadro** | 🔒 | |
|
||||
| Ghost Matter | **prízračná hmota** | 🔒 | |
|
||||
| the Nomai statue | **socha Nomai** | 🔒 | |
|
||||
| supernova | **supernova** | 🔒 | |
|
||||
| the time loop | **časová slučka** | 🔒 | |
|
||||
|
||||
## 5. Tools, UI & systems
|
||||
|
||||
| English | Slovak | Status | Notes |
|
||||
|---|---|---|---|
|
||||
| ship log | **lodný denník** | 🔒 | |
|
||||
| Rumor Mode (ship log) | **režim fám** | 🔒 | |
|
||||
| Map Mode (ship log) | **režim mapy** | 🔒 | |
|
||||
| Signalscope | **Signáloskop** | 🔒 | Device name (treated as a proper name, capital S). |
|
||||
| Little Scout / Scout | **Malý Skaut** / **Skaut** | 🔒 | The camera probe; capital S. Decline *Skauta*, *Skautom*. |
|
||||
| Scout Launcher | **Odpaľovač Skauta** | 🔒 | |
|
||||
| the Translator (Nomai) | **Prekladač** | 🔒 | |
|
||||
| Autopilot | **autopilot** | 🔒 | |
|
||||
| Landing Camera | **pristávacia kamera** | 🔒 | |
|
||||
|
||||
---
|
||||
|
||||
## 5b. Ship-log locations & DLC terms (locked, 2026-07-20)
|
||||
|
||||
Named places and recurring terms from the ship log. Descriptive location names not
|
||||
listed here are translated literally (River Lowlands → *Riečne nížiny*, Northern
|
||||
Glacier → *Severný ľadovec*, Fire Chamber → *Ohňová komora*, …).
|
||||
|
||||
| English | Slovak | Notes |
|
||||
|---|---|---|
|
||||
| The Hanging City | **Visuté mesto** | Brittle Hollow's Nomai city. |
|
||||
| The Sunless City | **Bezslnečné mesto** | Ember Twin's Nomai city. |
|
||||
| Orbital Probe Cannon | **Orbitálne delo sondy** | Modules: *Riadiaci / Štartovací modul*, *Modul sledovania sondy*. |
|
||||
| Cinder Isles *(DLC)* | **Vyhorené ostrovy** | |
|
||||
| High Energy Lab | **Vysokoenergetické laboratórium** | |
|
||||
| White Hole Station | **Stanica bielej diery** | |
|
||||
| Gravity Cannon | **Gravitačné delo** | |
|
||||
| Tower of Quantum Knowledge / Trials | **Veža kvantového poznania** / **Veža kvantových skúšok** | |
|
||||
| Quantum Shrine | **Kvantová svätyňa** | *Quantum X* → *kvantový/-á/-é X* throughout. |
|
||||
| Construction Yard | **Stavenisko** | |
|
||||
| Nomai Mines / Grave / Shipwreck | **Bane / Hrob / Vrak lode Nomai** | *X Nomai* (indeclinable). |
|
||||
| Escape Pod (1/2/3) | **Únikový modul (1/2/3)** | |
|
||||
| the Vessel | **Plavidlo** | |
|
||||
| anglerfish | **udicovka** (pl. *udicovky*) | The Dark Bramble monster fish. |
|
||||
| Nomai shuttle | **raketoplán Nomai** | |
|
||||
| astral body | **nebeské teleso** | |
|
||||
| slide reel *(DLC)* | **kotúč diapozitívov** | |
|
||||
| vault *(DLC)* | **trezor** | vault seal → *pečať trezoru*. |
|
||||
| the Prisoner *(DLC)* | **Väzeň** | An Owlk (*Soví človek*). |
|
||||
| Vision Torch / Artifact *(DLC)* | **Fakľa vízií** / **Artefakt** | |
|
||||
| mural | **nástenná maľba** | |
|
||||
| memory statue | **pamäťová socha** | Nomai statue that records memories. |
|
||||
| storage unit / mask | **úložná jednotka** / **maska** | Ash Twin Project memory components. |
|
||||
| clan | **klan** | Nomai social group. |
|
||||
| star system | **hviezdna sústava** | vs. *slnečná sústava* = solar system. |
|
||||
| pilgrimage | **púť** | Solanum's journey to the Quantum Moon. |
|
||||
| Nomai character names | *kept in English* | Solanum, Poke, Clary, Coleus, Melorae, Cassava, Yarrow, Pye, Conoy, Bells, … Decline the surrounding Slovak, not the name. |
|
||||
|
||||
**Character genders** (from English pronoun cues; drives Slovak verb/possessive
|
||||
gender): **feminine** — Solanum, Poke, Clary (Poke's sister), Ramie, Pye, Filix
|
||||
("her note"), Melorae ("Aunt Melorae"), Privet ("her brother"). **masculine** —
|
||||
Annona, Coleus, Avens (Daz's brother), Plume (has a brother). Everyone else defaults to **masculine**
|
||||
until an English cue says otherwise.
|
||||
|
||||
**Hearthian genders (cross-checked against the Czech mod, 2026-07-20).** Outer
|
||||
Wilds uses *they/them* for all Hearthians, so we defaulted **masculine** and
|
||||
verified against `shippy/outer-wilds-czech` (Czech is also grammatically
|
||||
gendered). Confirmed **masculine**: Chert, Esker, Gabbro, Riebeck, Feldspar,
|
||||
Gneiss, Marl, Mica, Spinel, Tektite, Tuff, Hornfels, Hal, Gossan, Slate.
|
||||
Corrected to **feminine** (Czech + English cues): **Arkose** (the ghost-matter
|
||||
kid — *"Slyšela jsem"*), **Porphy** (the sap-wine maker — *"dolila… dávku"*),
|
||||
and the **hide-and-seek kid** at idx 1627 (*"Chtěla jsem… otravná"*). **Filix**
|
||||
stays **feminine** (English "her note") even though the Czech mod rendered her
|
||||
masculine — English canon wins. Undetermined (no gendered self-reference either
|
||||
side; left masculine): Galena, Rutile, Tephra, Moraine. (Possessive of names in *-a*: *Annonov/-a/-o*,
|
||||
*Cassavov/-a/-o*, e.g. *Cassavovo Stavenisko*.) **Note:** Melorae was initially
|
||||
translated masculine in batch 7, then corrected to feminine once "Aunt Melorae"
|
||||
surfaced.
|
||||
|
||||
**Nomai voice tics:** "My gratitude" (their formal thanks) → **Moja vďaka**;
|
||||
"on the other appendage" (a hand-joke — Nomai have appendages, not hands) →
|
||||
**Na druhej končatine**. Keep this dry, precise, courteous register for Nomai.
|
||||
|
||||
## 6. Resolved decisions (2026-07-20 review)
|
||||
|
||||
1. **Planet names → translated** (not kept in English). ✅
|
||||
2. **Nomai → indeclinable**, kept as-is (alien species name). ✅
|
||||
3. **UI length** — not a concern: the text display supports variable lengths. ✅
|
||||
4. **DLC titles** — translate in prose (*Ozveny Oka*, *Cudzinec*); keep English
|
||||
only where a string functions as a store/product title. ✅ (`Echoes of the Eye`
|
||||
the DLC title still `❓` in §3 for that reason.)
|
||||
|
||||
## 7. Still open
|
||||
|
||||
- **`Twilight Twin`** (Nomai dialogue, warp-tower lines) — rendered provisionally as
|
||||
*Súmračné dvojča*. Unusual term; confirm meaning/rendering in review.
|
||||
- **`Echoes of the Eye`** as a product/menu title — translate everywhere, or keep
|
||||
English on title/store strings? (Prose already uses *Ozveny Oka*.)
|
||||
- Terms that will surface in the **dialogue** and **ship log** phases and aren't
|
||||
fixed yet: the Vessel interior locations, the Hanging City, the Sunless City,
|
||||
the High Energy Lab, the Quantum Shrine, DLC props (Slide Reel → *Kotúč
|
||||
diapozitívov*, Vision Torch → *Fakľa vízií*, the Artifact → *Artefakt*), etc.
|
||||
I'll raise these as we hit each category.
|
||||
@@ -1,123 +0,0 @@
|
||||
# Review notes — things to check in the Slovak human review pass
|
||||
|
||||
Consolidated list of wordplay, coined terms, gender guesses, and register calls
|
||||
that the machine-assisted first pass flagged. Work through these with a
|
||||
Slovak-speaking eye. Grouped by type; `idx` = position in the flat `<entry>`
|
||||
list where useful. See [`glossary.md`](glossary.md) and [`../PLAN.md`](../PLAN.md)
|
||||
for the locked terms and per-batch context.
|
||||
|
||||
---
|
||||
|
||||
## 1. Puns & wordplay (hardest to get right)
|
||||
|
||||
| Where | English | Current SK | Note |
|
||||
|---|---|---|---|
|
||||
| Gabbro, satellite (idx ~460–466) | "Ol' Spacey" (the deep-space satellite; "Ol'" = affectionate "old") | **Vesmírko** | Nickname folded to a diminutive that carries affection via form, not oldness. Line 465 ("'Ol'' is more a term of affection") therefore explains *starký/old* while the name is *Vesmírko* — mild disconnect. Consider a nickname that keeps the "old" beat, e.g. *Starký* / *Vesmírko starký*. |
|
||||
| Gabbro (idx 1353) | "you just got **Feldsparred**" | *...práve ťa **Feldsparovalo*** | Invented verb from a name; keep or rework. |
|
||||
| Gabbro (idx 399 etc.) | "**Statue Island** ...Get it?" (it's the *island* with the *statue*) | **Ostrov sôch** ...Chápeš? | The "get it?" gag barely lands in SK since the wordplay is thin even in EN. OK, but confirm. |
|
||||
| Chert (idx 1979) | "Keep **an eye or four** on the stars" (Hearthians have >2 eyes) | *Maj oko, aj štyri, na hviezdach* | ✅ reworded per review (was *Maj oči — pokojne aj štyri —*). |
|
||||
| Player self (idx 252) | "we are the **Feldspar** of weird time stuff" | *sme **Feldsparom** čudných časových vecí* | Idiom "the X of Y"; fine but review. |
|
||||
| Ghost-matter kid (idx 1702) | "All **pew pew pew**!" | *Také **pyu pyu pyu**!* | Onomatopoeia choice. |
|
||||
| Feldspar note (idx 1350) | "Hornfels, **ya burnt marshmallow**" (insult) | *Hornfels, ty **pripálený marshmallow*** | Insult + the kept loanword *marshmallow* (see §2). |
|
||||
| Porphy, sap wine (idx 1476, 1478, 1490) | "**The Good Stuff**"; bottles labeled "structural collapse" / "house fire" | **Tá Dobrota** (standardized; was mixed *To Pravé*/*Tá Dobrota*); „zrútenie konštrukcie" / „požiar domu" | Bar/booze humor; Porphy is **feminine** (§3). |
|
||||
| Chert (idx 1994) | "On a **scale of one to dead**, I'd give it a seven or eight" | *Na škále **od jeden po smrť**...* | Keep the deadpan. |
|
||||
| Feldspar jellyfish journal (idx 2181) | "Boring crashes: 0 (a personal best!)" / "entry #... 'not 1'" | translated literally | Feldspar's swagger; check voice. |
|
||||
| Fishing rhymes (idx 1540, 1567, 1576) | fishing rhyme/song/tune couplets (the 3rd deliberately fails to rhyme) | rendered **loosely to keep a rhyme** | ✅ 1567 reworked to *…ech, asi mi nesedí táto **návnadička*** (rhymes *pesnička/návnadička*, keeps "bait is wrong"). 1576 intentionally drops the rhyme (matches the EN joke). |
|
||||
| Nomai, Pye/Ramie (batch 5–6) | "gas / aeriform" state-of-matter puns; Pye's supernova/"gas" humor | flagged in batch notes | Physics/gas double meaning — verify it survives. |
|
||||
| Nomai, Conoy (batch 6) | "lose his head" joke | flagged | Idiom. |
|
||||
| Nomai, Melorae (batch 7) | "my **sedimentary** friend" (geologist pun) | flagged | Rock pun on "sedentary". |
|
||||
| Nomai idiom (glossary) | "on the other **appendage**" (hand-joke; Nomai have appendages) | **Na druhej končatine** | Locked, but re-read in context. |
|
||||
| Idaea (batch 11) | Sun Station "mission" humor | flagged | Deadpan Nomai humor. |
|
||||
|
||||
**Character names are themselves geology/rock puns** (Slate, Feldspar, Gabbro,
|
||||
Chert, Gneiss, Tuff, Tephra, Porphy, Arkose, Mica, Moraine, Hornfels, …) — kept
|
||||
in English by design (see glossary §1). No action unless we ever localize names.
|
||||
|
||||
---
|
||||
|
||||
## 2. Coined / provisional terms (no prior canon — confirm rendering)
|
||||
|
||||
| English | Current SK | Status |
|
||||
|---|---|---|
|
||||
| Ol' Spacey | **Vesmírko** | provisional (see §1) |
|
||||
| Statue Island (Gabbro's coinage) | **Ostrov sôch** | provisional |
|
||||
| Lunar Outpost (Esker's, on the Attlerock) | **Mesačná základňa** | provisional |
|
||||
| Youngbark Crater | **Kráter Mladej kôry** | provisional (blockC) |
|
||||
| Quantum Grove Crater | **Kráter Kvantového hája** | provisional (blockC) |
|
||||
| The Good Stuff (sap wine) | **Tá Dobrota** | standardized this pass |
|
||||
| marshmallow | **marshmallow** (kept) | decide: keep loanword or *sladká pena*? Be consistent. |
|
||||
| Twilight Twin (Nomai warp-tower lines) | **Súmračné dvojča** | ❓ unusual term — confirm meaning/rendering |
|
||||
| Echoes of the Eye (DLC title) | **Ozveny Oka** in prose | ❓ keep EN on store/menu title strings? |
|
||||
| Distant Nomai places (batch 10) | **Súmračná galaxia**, **Čierna skala**, **Jasná iskra** | flagged |
|
||||
|
||||
---
|
||||
|
||||
## 3. Gender — cross-checked against the Czech mod ✅
|
||||
|
||||
Outer Wilds uses **they/them for all Hearthians**; Slovak forces a gender, so the
|
||||
first pass **defaulted masculine**. We then cross-checked every gendered
|
||||
self-reference against `shippy/outer-wilds-czech` (Czech is also grammatically
|
||||
gendered) — only **3** disagreements surfaced across the whole file, now resolved:
|
||||
|
||||
- **Arkose** (ghost-matter kid) → **corrected to feminine** (*Slyšela jsem*).
|
||||
- **Porphy** (sap-wine maker) → **corrected to feminine** (*dolila dávku*).
|
||||
- **Filix** — Czech has her masculine, but English says *"her note"*, so she
|
||||
**stays feminine** (English canon wins).
|
||||
- Also flipped the **hide-and-seek kid** at idx 1627 to feminine (*Chtěla
|
||||
jsem… otravná*).
|
||||
|
||||
**Confirmed masculine** (Czech agrees): Chert, Esker, Gabbro, Riebeck, Feldspar,
|
||||
Gneiss, Marl, Mica, Spinel, Tektite, Tuff, Hornfels, Hal, Gossan, Slate.
|
||||
**Undetermined** (no gendered self-reference either side; left masculine): Galena,
|
||||
Rutile, Tephra, Moraine — worth a glance in-game but low-risk.
|
||||
**Locked female (EN cues):** Solanum, Poke, Clary, Ramie, Pye, Filix, Melorae,
|
||||
Privet. **Locked male:** Annona, Coleus, Avens, Plume, Idaea.
|
||||
|
||||
---
|
||||
|
||||
## 4. Register & length
|
||||
|
||||
- **Nomai text walls** — keep the formal, precise, courteous voice; watch length
|
||||
vs. the in-game panels (utility supports variable length, but very long walls
|
||||
should stay tight).
|
||||
- **Chert's panic stammer** (idx 2029–2031, 2076–2077) — rendered as
|
||||
*a-a-ale / d-d-dúfam / m-možno*. Check it reads as anxious, not broken.
|
||||
- **Kids' register** — playful, casual *ty*; player often *mláďa*. Make sure the
|
||||
kid voices don't sound adult.
|
||||
- **Player self-talk** (the "two of you" convo, idx 169–308) — both speakers are
|
||||
the player, masculine, mutual *ty*; screams left verbatim.
|
||||
|
||||
---
|
||||
|
||||
## 5b. Coined this pass (audit against the game's own table, 2026-07-21)
|
||||
|
||||
The upstream English template (from the Localization Utility repo) is slightly out
|
||||
of date versus the shipped game. Extracting the game's own English
|
||||
`TranslationTable_XML` from `resources.assets` and diffing it found 17 keys we
|
||||
didn't cover and 7 values still in English. New renderings to sanity-check:
|
||||
|
||||
| English | Current SK | Note |
|
||||
|---|---|---|
|
||||
| Stepping Stone District | **Štvrť nášľapných kameňov** | matches *Jaskyňa nášľapných kameňov* |
|
||||
| Anglerfish Overlook District | **Štvrť vyhliadky na udicovku** | matches *Vyhliadka na udicovku* |
|
||||
| Eye Shrine District | **Štvrť Svätyne Oka** | new |
|
||||
| Black Hole Forge controls | **Ovládanie Kovárne čiernych dier** | was left in English |
|
||||
| Divergence Meter / world line | **Merač divergencie** / **svetočiara** | Steins;Gate easter egg |
|
||||
| *El Psy Congroo* | left verbatim | Steins;Gate catchphrase, not translatable |
|
||||
|
||||
Two dialogue keys (`sun station 2`, `sun station 5a`) had `<pause>` in the template
|
||||
where the game has `<Pause>`; both spellings are now present so either build matches.
|
||||
Likewise the ship log key for Solanum entering the Eye: the template misspells
|
||||
*concious*, the game says *conscious* — both are shipped.
|
||||
|
||||
**Re-run the audit after any game update** — it is the only reliable way to catch
|
||||
strings the template is missing.
|
||||
|
||||
---
|
||||
|
||||
## 5. Left verbatim on purpose (not for translation)
|
||||
|
||||
Panic-scream onomatopoeia (idx 174, 267–286), sick-noises (*Hurgh…*, idx
|
||||
1666/1685), shy-kid silences (`…`), Kickstarter backer credit **names** (idx
|
||||
2408–2415), and the ASCII-art easter eggs (idx 2416–2418, only embedded words
|
||||
like LOADING → *NAČÍTAVA SA* were translated). Leave these as-is.
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"author": "Jaroslav Beneš",
|
||||
"name": "Slovak Localization / Slovenčina",
|
||||
"uniqueName": "Homer.SlovakTranslation",
|
||||
"version": "0.1.0",
|
||||
"version": "1.0.0",
|
||||
"owmlVersion": "2.5.2",
|
||||
"dependencies": [
|
||||
"xen.LocalizationUtility"
|
||||
|
||||
Reference in New Issue
Block a user