Compare commits
30 Commits
main
..
832a92783b
| Author | SHA1 | Date | |
|---|---|---|---|
| 832a92783b | |||
| 41ee614d33 | |||
| 59ff1bf86a | |||
| 26435c05ec | |||
| 9935bf68fb | |||
| ea50c6dfa6 | |||
| 299f69ab8d | |||
| 03783a1528 | |||
| c4ffd505c0 | |||
| 161ec1bab3 | |||
| bc1b3f0cb1 | |||
| 446e1d6934 | |||
| 4fab56c983 | |||
| 1d151c8e8e | |||
| d97f9e109e | |||
| 4828a450ea | |||
| 363f7ac93b | |||
| 96864b88b7 | |||
| e7645d0f72 | |||
| ab028a0a98 | |||
| 07d9818a91 | |||
| bfd46ab5e4 | |||
| 3d667b7013 | |||
| e3f562273b | |||
| 8100adec75 | |||
| 3dc47474e3 | |||
| b36d17f9c4 | |||
| 1082d91e3b | |||
| ffd6bbe6b5 | |||
| e66ce54d3e |
@@ -1,32 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# 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.
|
||||||
@@ -0,0 +1,304 @@
|
|||||||
|
# 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.*
|
> the base game and the Echoes of the Eye DLC.*
|
||||||
|
|
||||||
**Stav / Status:** 🚧 **Work in progress** — the mod scaffold and translation are
|
**Stav / Status:** 🚧 **Work in progress** — the mod scaffold and translation are
|
||||||
being built. See the [Roadmap](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki/Roadmap).
|
being built. See [`PLAN.md`](PLAN.md) for the roadmap.
|
||||||
|
|
||||||
Outer Wilds officially ships in 12 languages; Slovak is not one of them. This mod
|
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 —
|
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`.
|
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
|
> Until the first release is published, the mod is not yet in the Mod Manager
|
||||||
> database — see the [Roadmap](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki/Roadmap) for how to build it from source.
|
> database — see [`PLAN.md`](PLAN.md) for how to build it from source.
|
||||||
|
|
||||||
## Contributing / Prispievanie
|
## Contributing / Prispievanie
|
||||||
|
|
||||||
@@ -45,24 +45,21 @@ Translation fixes are very welcome — the goal is natural, consistent Slovak.
|
|||||||
**Never change the `<key>`** — it is the English identifier the game matches on.
|
**Never change the `<key>`** — it is the English identifier the game matches on.
|
||||||
- Preserve all inline formatting exactly, e.g. `<color=orange>…</color>`,
|
- Preserve all inline formatting exactly, e.g. `<color=orange>…</color>`,
|
||||||
`<i>`, and speaker prefixes like `POKE:`.
|
`<i>`, and speaker prefixes like `POKE:`.
|
||||||
- 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
|
- Follow the terminology in `docs/glossary.md` so names (Nomai, the Eye, Ash Twin
|
||||||
Project, …) stay consistent across the whole game.
|
Project, …) stay consistent across the whole game.
|
||||||
|
|
||||||
See the [Working notes](https://git.houmeres.sk/Houmeres/Outer-Wilds-SK-Translation-Mod/wiki/Working-notes) for the full conventions and repo layout.
|
See [`CLAUDE.md`](CLAUDE.md) for the full conventions and repo layout.
|
||||||
|
|
||||||
## License & disclaimer
|
## License & disclaimer
|
||||||
|
|
||||||
The **original mod code and the Slovak translation** in this repository are
|
The **original mod code and the Slovak translation** in this repository are
|
||||||
released under the [MIT License](LICENSE).
|
released under the [MIT License](LICENSE).
|
||||||
|
|
||||||
The bundled fallback font in `assets/slovakfont` is
|
The bundled UI font in `assets/slovakfont` is **[Cabin](https://github.com/impallari/Cabin)**
|
||||||
**[Cabin](https://github.com/impallari/Cabin)** by the Cabin Project Authors, used
|
by the Cabin Project Authors, used under the **SIL Open Font License 1.1**
|
||||||
under the **SIL Open Font License 1.1** (see
|
(see [`assets/Cabin-OFL.txt`](assets/Cabin-OFL.txt)). It is only used for the few
|
||||||
[`assets/Cabin-OFL.txt`](assets/Cabin-OFL.txt)). The game's own menu and HUD fonts
|
menu/HUD elements whose stock font was never baked with Slovak caron glyphs — see
|
||||||
were never baked with Slovak caron glyphs, so those labels are redrawn with a font
|
[`SlovakFont.cs`](SlovakFont.cs).
|
||||||
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
|
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,
|
endorsed by Mobius Digital or Annapurna Interactive.** *Outer Wilds*, its story,
|
||||||
|
|||||||
+112
-222
@@ -1,8 +1,9 @@
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using OWML.Common;
|
using OWML.Common;
|
||||||
using OWML.ModHelper;
|
using OWML.ModHelper;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
@@ -14,70 +15,36 @@ namespace SlovakTranslation
|
|||||||
/// Outer Wilds renders Latin languages with a handful of *static* font atlases,
|
/// Outer Wilds renders Latin languages with a handful of *static* font atlases,
|
||||||
/// and only some of them were baked with Latin Extended-A:
|
/// and only some of them were baked with Latin Extended-A:
|
||||||
///
|
///
|
||||||
/// Adobe - SerifGothicStd (+ExtraBold) menus 253 glyphs — no carons
|
/// Gill Sans MT / Gill Sans MT Menu (menus, prompts) 243 glyphs — no carons
|
||||||
/// Gill Sans MT (+Menu, Bold) HUD prompts 243 glyphs — no carons
|
/// ParaType - Futura PT Medium (language font) 663 glyphs — complete
|
||||||
/// ParaType - Futura PT Medium dialogue 663 glyphs — complete
|
/// SpaceMono-Regular (translator) 612 glyphs — complete
|
||||||
/// SpaceMono-Regular translator 612 glyphs — complete
|
|
||||||
///
|
///
|
||||||
/// That is why dialogue and the Nomai translator always looked right while
|
/// That is why dialogue and the Nomai translator always looked right while
|
||||||
/// "Pokračovať" came out as "Pokra ova".
|
/// "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.
|
||||||
///
|
///
|
||||||
/// Registering a whole custom language font via the Localization Utility fixes
|
/// So instead we leave the language font alone and swap fonts *only* where the
|
||||||
/// the menus, but it also flips <c>TextTranslation.IsLanguageLatin()</c> to
|
/// vanilla one physically cannot draw Slovak — checked at runtime with
|
||||||
/// false, which drags dialogue, the translator and the ship log off their
|
/// <c>Font.HasCharacter</c>, so we never touch a font that renders fine.
|
||||||
/// 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>
|
/// </summary>
|
||||||
internal static class SlovakFont
|
internal static class SlovakFont
|
||||||
{
|
{
|
||||||
/// <summary>Cabin (SIL OFL 1.1), a humanist sans in the Gill Sans lineage, used
|
/// <summary>Cabin (SIL OFL 1.1), a humanist sans close to the vanilla Gill Sans MT.
|
||||||
/// where the game has no dynamic cut of its own. Dynamic, so it can draw any
|
/// Shipped as a dynamic font, so it can draw any glyph Slovak needs.</summary>
|
||||||
/// glyph Slovak needs.</summary>
|
|
||||||
private static Font _font;
|
private static Font _font;
|
||||||
|
|
||||||
/// <summary>The letters Slovak adds on top of plain ASCII. Only these are worth
|
/// <summary>Characters the vanilla menu atlas is missing. If a font can draw all
|
||||||
/// probing — anything else in the text was already fine in English.</summary>
|
/// of these it is left completely alone.</summary>
|
||||||
private const string SlovakLetters = "áäčďéíĺľňóôŕšťúýžÁÄČĎÉÍĹĽŇÓÔŔŠŤÚÝŽ";
|
private static readonly char[] Probe = { 'č', 'ď', 'ĺ', 'ľ', 'ň', 'ŕ', 'ť', 'ž', 'ô', 'ä' };
|
||||||
|
|
||||||
/// <summary>Stylised display faces (the ship's readouts, seven-segment digits).
|
private static readonly Dictionary<int, bool> _coverage = new Dictionary<int, bool>();
|
||||||
/// 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 bool Loaded => _font != null;
|
||||||
|
|
||||||
internal static void Load(ModBehaviour mod)
|
internal static void Load(ModBehaviour mod)
|
||||||
{
|
{
|
||||||
_mod = mod;
|
|
||||||
var path = mod.ModHelper.Manifest.ModFolderPath + "assets/slovakfont";
|
var path = mod.ModHelper.Manifest.ModFolderPath + "assets/slovakfont";
|
||||||
var bundle = AssetBundle.LoadFromFile(path);
|
var bundle = AssetBundle.LoadFromFile(path);
|
||||||
if (bundle == null)
|
if (bundle == null)
|
||||||
@@ -90,7 +57,7 @@ namespace SlovakTranslation
|
|||||||
{
|
{
|
||||||
if (font.name != "SlovakUI") continue;
|
if (font.name != "SlovakUI") continue;
|
||||||
_font = font;
|
_font = font;
|
||||||
Object.DontDestroyOnLoad(font);
|
UnityEngine.Object.DontDestroyOnLoad(font);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,199 +65,122 @@ namespace SlovakTranslation
|
|||||||
mod.ModHelper.Console.WriteLine("Font bundle has no 'SlovakUI' font.", MessageType.Error);
|
mod.ModHelper.Console.WriteLine("Font bundle has no 'SlovakUI' font.", MessageType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Give <paramref name="text"/> a font that can draw Slovak, or hand back
|
/// <summary>Returns <paramref name="font"/> unchanged unless Slovenčina is the
|
||||||
/// the game's own font once it is no longer needed.</summary>
|
/// active language and that font cannot draw Slovak.</summary>
|
||||||
internal static void Apply(Text text)
|
internal static Font Fix(Font font)
|
||||||
{
|
{
|
||||||
if (_font == null || text == null) return;
|
if (_font == null || font == null || font == _font) return font;
|
||||||
|
|
||||||
var current = text.font;
|
// Dynamic fonts rasterise straight from an embedded font file; every one the
|
||||||
Font stored;
|
// game ships for Latin covers Slovak, and HasCharacter is unreliable for them.
|
||||||
var swapped = _swapped.TryGetValue(text, out stored) && stored != null &&
|
if (font.dynamic) return font;
|
||||||
current == SubstituteFor(stored);
|
|
||||||
|
|
||||||
// If anything else assigned a font since our swap, that is the new baseline.
|
if (!IsActive()) return font;
|
||||||
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();
|
var id = font.GetInstanceID();
|
||||||
string gaps;
|
if (!_coverage.TryGetValue(id, out var complete))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (!font.HasCharacter(c)) builder.Append(c);
|
complete = true;
|
||||||
|
foreach (var c in Probe)
|
||||||
|
{
|
||||||
|
if (font.HasCharacter(c)) continue;
|
||||||
|
complete = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_coverage[id] = complete;
|
||||||
}
|
}
|
||||||
gaps = builder.ToString();
|
|
||||||
_gaps[id] = gaps;
|
|
||||||
|
|
||||||
if (gaps.Length > 0)
|
return complete ? font : _font;
|
||||||
{
|
|
||||||
_mod?.ModHelper.Console.WriteLine(
|
|
||||||
$"font \"{font.name}\" cannot draw \"{gaps}\" — " +
|
|
||||||
(IsStylised(font.name) ? "substituting only where needed" : "substituting everywhere"),
|
|
||||||
MessageType.Info);
|
|
||||||
}
|
|
||||||
return gaps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsStylised(string fontName)
|
#region "is Slovenčina selected?"
|
||||||
{
|
|
||||||
foreach (var stylised in Stylised)
|
|
||||||
{
|
|
||||||
if (fontName.IndexOf(stylised, System.StringComparison.OrdinalIgnoreCase) >= 0) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>True while a mod-registered language is selected. The Localization
|
// The Localization Utility invents a TextTranslation.Language value for each
|
||||||
/// Utility appends custom languages past <c>Language.TOTAL</c>, and treats
|
// custom language, so it is not in the enum at compile time. Ask the utility
|
||||||
/// everything up to it as vanilla — same test it uses itself.</summary>
|
// once, then cache the value and compare enums from then on.
|
||||||
private static bool CustomLanguageActive()
|
private static bool _resolved;
|
||||||
|
private static TextTranslation.Language _slovak;
|
||||||
|
private static MethodInfo _tryGetLanguage;
|
||||||
|
private static object _utility;
|
||||||
|
|
||||||
|
private static bool IsActive()
|
||||||
{
|
{
|
||||||
if (TextTranslation.s_theTable == null) return false;
|
if (TextTranslation.s_theTable == null) return false;
|
||||||
return TextTranslation.Get().GetLanguage() > TextTranslation.Language.TOTAL;
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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>
|
/// <summary>
|
||||||
/// Hooks: every label as it appears or changes, plus a sweep whenever the game
|
/// Every place the game hands out a font that is not the language font. Each one
|
||||||
/// reassigns fonts wholesale.
|
/// runs through <see cref="SlovakFont.Fix"/>, which is a no-op unless the font
|
||||||
|
/// really is missing Slovak glyphs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
internal static class SlovakFontPatches
|
internal static class SlovakFontPatches
|
||||||
{
|
{
|
||||||
[HarmonyPostfix, HarmonyPatch(typeof(Text), "OnEnable")]
|
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetMenuFont))]
|
||||||
public static void TextEnabled(Text __instance) => SlovakFont.Apply(__instance);
|
public static void MenuFont(ref Font __result) => __result = SlovakFont.Fix(__result);
|
||||||
|
|
||||||
[HarmonyPostfix, HarmonyPatch(typeof(Text), "text", MethodType.Setter)]
|
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetTranslatorFont))]
|
||||||
public static void TextChanged(Text __instance) => SlovakFont.Apply(__instance);
|
public static void TranslatorFont(ref Font __result) => __result = SlovakFont.Fix(__result);
|
||||||
|
|
||||||
// The game reassigns fonts wholesale when the language changes. Re-deciding here
|
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetShipLogFont))]
|
||||||
// is safe: our own assignment re-enters once, finds the state already correct,
|
public static void ShipLogFont(ref Font __result) => __result = SlovakFont.Fix(__result);
|
||||||
// and stops.
|
|
||||||
[HarmonyPostfix, HarmonyPatch(typeof(Text), "font", MethodType.Setter)]
|
|
||||||
public static void FontAssigned(Text __instance) => SlovakFont.Apply(__instance);
|
|
||||||
|
|
||||||
[HarmonyPostfix, HarmonyPatch(typeof(TextTranslation), nameof(TextTranslation.SetLanguage))]
|
[HarmonyPostfix, HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetShipLogCardFont))]
|
||||||
public static void LanguageChanged() => SlovakFont.ApplyToAll();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,25 +47,8 @@ namespace SlovakTranslation
|
|||||||
if (SlovakFont.Loaded)
|
if (SlovakFont.Loaded)
|
||||||
{
|
{
|
||||||
new Harmony("Homer.SlovakTranslation").PatchAll();
|
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);
|
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.
+1
-4
@@ -1,6 +1,3 @@
|
|||||||
{
|
{
|
||||||
"enabled": true,
|
"enabled": true
|
||||||
"settings": {
|
|
||||||
"preferGameTypeface": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
# 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.
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
# 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š",
|
"author": "Jaroslav Beneš",
|
||||||
"name": "Slovak Localization / Slovenčina",
|
"name": "Slovak Localization / Slovenčina",
|
||||||
"uniqueName": "Homer.SlovakTranslation",
|
"uniqueName": "Homer.SlovakTranslation",
|
||||||
"version": "1.0.0",
|
"version": "0.1.0",
|
||||||
"owmlVersion": "2.5.2",
|
"owmlVersion": "2.5.2",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"xen.LocalizationUtility"
|
"xen.LocalizationUtility"
|
||||||
|
|||||||
Reference in New Issue
Block a user