feat: Add prologue voiceover loading, implement new game systems, and introduce development logs
This commit is contained in:
439
MULTI_LANGUAGE_PLAN.md
Normal file
439
MULTI_LANGUAGE_PLAN.md
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
# 🌍 MULTI-LANGUAGE LOCALIZATION PLAN
|
||||||
|
**Game:** Mrtva Dolina / Death Valley
|
||||||
|
**Date:** January 4, 2026
|
||||||
|
**Status:** Planning Phase
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 CORE LANGUAGES
|
||||||
|
|
||||||
|
### **Primary (DONE):** ✅
|
||||||
|
1. **Slovenian (sl-SI)** - Native language, COMPLETE
|
||||||
|
- ✅ All dialogue translated
|
||||||
|
- ✅ UI translated
|
||||||
|
- ✅ 12 prologue voiceovers (Rok + Petra)
|
||||||
|
- ✅ Real character portraits
|
||||||
|
|
||||||
|
### **Target Languages (TODO):**
|
||||||
|
2. **English (en-US)** 🇺🇸
|
||||||
|
3. **German (de-DE)** 🇩🇪
|
||||||
|
4. **Italian (it-IT)** 🇮🇹
|
||||||
|
5. **Croatian (hr-HR)** 🇭🇷
|
||||||
|
6. **Serbian (sr-RS)** 🇷🇸
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 IMPLEMENTATION STRATEGY
|
||||||
|
|
||||||
|
### **Phase 1: Localization System** (Week 1)
|
||||||
|
|
||||||
|
**Goal:** Create dynamic language switching system
|
||||||
|
|
||||||
|
**Tasks:**
|
||||||
|
1. ✅ Create `LocalizationSystem.js` (already exists!)
|
||||||
|
2. Create language JSON files:
|
||||||
|
- `assets/localization/en-US.json`
|
||||||
|
- `assets/localization/de-DE.json`
|
||||||
|
- `assets/localization/it-IT.json`
|
||||||
|
- `assets/localization/hr-HR.json`
|
||||||
|
- `assets/localization/sr-RS.json`
|
||||||
|
- `assets/localization/sl-SI.json` (extract current)
|
||||||
|
|
||||||
|
3. Update `PrologueScene.js` to use LocalizationSystem
|
||||||
|
4. Create language selector UI (main menu)
|
||||||
|
|
||||||
|
**Structure:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ui": {
|
||||||
|
"skip": "Press ESC to skip",
|
||||||
|
"autoAdvance": "Press SPACE to toggle auto-advance"
|
||||||
|
},
|
||||||
|
"prologue": {
|
||||||
|
"scene_01": {
|
||||||
|
"speaker": "NARRATOR",
|
||||||
|
"text": "Year 2084. The zombie virus destroyed the world."
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Phase 2: Translation** (Week 2-3)
|
||||||
|
|
||||||
|
**Goal:** Translate all game text to 5 languages
|
||||||
|
|
||||||
|
**Content to Translate:**
|
||||||
|
|
||||||
|
**1. Prologue (12 scenes):**
|
||||||
|
- Scene descriptions
|
||||||
|
- Character dialogue
|
||||||
|
- Narrator text
|
||||||
|
|
||||||
|
**2. UI Elements:**
|
||||||
|
- Menu items
|
||||||
|
- Button labels
|
||||||
|
- Tutorial text
|
||||||
|
- Item descriptions
|
||||||
|
- Quest text
|
||||||
|
|
||||||
|
**3. NPC Dialogue:**
|
||||||
|
- Gronk conversations
|
||||||
|
- Town NPCs
|
||||||
|
- Quest givers
|
||||||
|
|
||||||
|
**Translation Methods:**
|
||||||
|
|
||||||
|
**Option A: Professional Translation** (BEST)
|
||||||
|
- Hire freelance translators (Fiverr, Upwork)
|
||||||
|
- ~$50-100 per language for game text
|
||||||
|
- Native speakers ensure quality
|
||||||
|
|
||||||
|
**Option B: AI Translation** (FAST)
|
||||||
|
- Use DeepL API (better than Google)
|
||||||
|
- Manual review by native speaker
|
||||||
|
- Free tier: 500,000 characters/month
|
||||||
|
|
||||||
|
**Option C: Community Translation** (FREE)
|
||||||
|
- Open GitHub for community contributions
|
||||||
|
- Steam forum volunteers
|
||||||
|
- Quality varies
|
||||||
|
|
||||||
|
**Recommendation:** Start with **DeepL + Manual Review**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Phase 3: Voiceover Generation** (Week 4-5)
|
||||||
|
|
||||||
|
**Goal:** Generate voiceovers for all 5 languages
|
||||||
|
|
||||||
|
**Available Voices (Microsoft Edge TTS):**
|
||||||
|
|
||||||
|
**English (en-US):**
|
||||||
|
- Male: `en-US-GuyNeural` (Kai)
|
||||||
|
- Female: `en-US-JennyNeural` (Ana)
|
||||||
|
- Narrator: `en-US-ChristopherNeural`
|
||||||
|
|
||||||
|
**German (de-DE):**
|
||||||
|
- Male: `de-DE-ConradNeural` (Kai)
|
||||||
|
- Female: `de-DE-KatjaNeural` (Ana)
|
||||||
|
- Narrator: `de-DE-KillianNeural`
|
||||||
|
|
||||||
|
**Italian (it-IT):**
|
||||||
|
- Male: `it-IT-DiegoNeural` (Kai)
|
||||||
|
- Female: `it-IT-ElsaNeural` (Ana)
|
||||||
|
- Narrator: `it-IT-GiuseppeNeural`
|
||||||
|
|
||||||
|
**Croatian (hr-HR):**
|
||||||
|
- Male: `hr-HR-SreckoNeural` (Kai)
|
||||||
|
- Female: `hr-HR-GabrijelaNeural` (Ana)
|
||||||
|
|
||||||
|
**Serbian (sr-RS):**
|
||||||
|
- Male: `sr-RS-NicholasNeural` (Kai)
|
||||||
|
- Female: `sr-RS-SophieNeural` (Ana)
|
||||||
|
|
||||||
|
**Generation Scripts:**
|
||||||
|
|
||||||
|
Create automated scripts for each language:
|
||||||
|
```bash
|
||||||
|
# ai_voice_gen/generate_prologue_english.sh
|
||||||
|
# ai_voice_gen/generate_prologue_german.sh
|
||||||
|
# ai_voice_gen/generate_prologue_italian.sh
|
||||||
|
# ai_voice_gen/generate_prologue_croatian.sh
|
||||||
|
# ai_voice_gen/generate_prologue_serbian.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Folder Structure:**
|
||||||
|
```
|
||||||
|
assets/audio 🔴/voiceover/
|
||||||
|
├── prologue_sl/ (Slovenian - DONE)
|
||||||
|
├── prologue_en/ (English)
|
||||||
|
├── prologue_de/ (German)
|
||||||
|
├── prologue_it/ (Italian)
|
||||||
|
├── prologue_hr/ (Croatian)
|
||||||
|
└── prologue_sr/ (Serbian)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Phase 4: Integration** (Week 6)
|
||||||
|
|
||||||
|
**Goal:** Wire everything together
|
||||||
|
|
||||||
|
**Tasks:**
|
||||||
|
|
||||||
|
1. **Update PreloadScene:**
|
||||||
|
- Load language files
|
||||||
|
- Detect user's OS language (default)
|
||||||
|
- Load appropriate voiceover folder
|
||||||
|
|
||||||
|
2. **Language Selector UI:**
|
||||||
|
```
|
||||||
|
[MAIN MENU]
|
||||||
|
├── New Game
|
||||||
|
├── Continue
|
||||||
|
├── Options
|
||||||
|
│ └── Language ◄ NEW!
|
||||||
|
│ ├── 🇸🇮 Slovenščina
|
||||||
|
│ ├── 🇬🇧 English
|
||||||
|
│ ├── 🇩🇪 Deutsch
|
||||||
|
│ ├── 🇮🇹 Italiano
|
||||||
|
│ ├── 🇭🇷 Hrvatski
|
||||||
|
│ └── 🇷🇸 Srpski
|
||||||
|
└── Quit
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Dynamic Loading:**
|
||||||
|
```javascript
|
||||||
|
// PrologueScene.preload()
|
||||||
|
const lang = this.game.settings.language || 'sl-SI';
|
||||||
|
|
||||||
|
// Load appropriate audio
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
const num = i.toString().padStart(2, '0');
|
||||||
|
this.load.audio(
|
||||||
|
`prologue_${num}`,
|
||||||
|
`assets/audio 🔴/voiceover/prologue_${lang.split('-')[0]}/prologue_${num}.wav`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load localization
|
||||||
|
this.load.json('localization', `assets/localization/${lang}.json`);
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Runtime Switching:**
|
||||||
|
- Save language preference to localStorage
|
||||||
|
- Reload scene when language changes
|
||||||
|
- Keep game state
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 PRODUCTION TIMELINE
|
||||||
|
|
||||||
|
| Week | Task | Deliverable |
|
||||||
|
|------|------|-------------|
|
||||||
|
| **1** | Localization System | Language JSON structure |
|
||||||
|
| **2** | English Translation | en-US.json + voiceovers |
|
||||||
|
| **3** | German + Italian | de-DE.json, it-IT.json + voice |
|
||||||
|
| **4** | Croatian + Serbian | hr-HR.json, sr-RS.json + voice |
|
||||||
|
| **5** | Integration | Language selector UI |
|
||||||
|
| **6** | Testing | All languages verified |
|
||||||
|
|
||||||
|
**Total Time:** ~6 weeks (1.5 months)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💰 COST ESTIMATE
|
||||||
|
|
||||||
|
### **Option 1: Professional Translation**
|
||||||
|
- 5 languages × $75/language = **$375**
|
||||||
|
- Voiceovers: FREE (Edge TTS)
|
||||||
|
- **Total: $375**
|
||||||
|
|
||||||
|
### **Option 2: AI + Review**
|
||||||
|
- DeepL API: FREE (under limit)
|
||||||
|
- Native speaker review: $25/language × 5 = **$125**
|
||||||
|
- Voiceovers: FREE (Edge TTS)
|
||||||
|
- **Total: $125**
|
||||||
|
|
||||||
|
### **Option 3: DIY**
|
||||||
|
- Your time: ~40 hours
|
||||||
|
- Voiceovers: FREE (Edge TTS)
|
||||||
|
- **Total: $0** (time only)
|
||||||
|
|
||||||
|
**Recommendation:** **Option 2** (AI + Review) - Best balance of quality/cost/speed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ TECHNICAL IMPLEMENTATION
|
||||||
|
|
||||||
|
### **1. Create Localization Manager**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// src/systems/LocalizationManager.js
|
||||||
|
class LocalizationManager {
|
||||||
|
constructor(game) {
|
||||||
|
this.game = game;
|
||||||
|
this.currentLanguage = 'sl-SI';
|
||||||
|
this.translations = {};
|
||||||
|
this.availableLanguages = [
|
||||||
|
{ code: 'sl-SI', name: 'Slovenščina', flag: '🇸🇮' },
|
||||||
|
{ code: 'en-US', name: 'English', flag: '🇬🇧' },
|
||||||
|
{ code: 'de-DE', name: 'Deutsch', flag: '🇩🇪' },
|
||||||
|
{ code: 'it-IT', name: 'Italiano', flag: '🇮🇹' },
|
||||||
|
{ code: 'hr-HR', name: 'Hrvatski', flag: '🇭🇷' },
|
||||||
|
{ code: 'sr-RS', name: 'Srpski', flag: '🇷🇸' }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
loadLanguage(langCode) {
|
||||||
|
// Load JSON file
|
||||||
|
this.translations = this.game.cache.json.get(`lang_${langCode}`);
|
||||||
|
this.currentLanguage = langCode;
|
||||||
|
localStorage.setItem('game_language', langCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
getText(key) {
|
||||||
|
const keys = key.split('.');
|
||||||
|
let value = this.translations;
|
||||||
|
for (const k of keys) {
|
||||||
|
value = value[k];
|
||||||
|
if (!value) return key; // Fallback
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
getVoiceFolder() {
|
||||||
|
const langShort = this.currentLanguage.split('-')[0];
|
||||||
|
return `prologue_${langShort}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2. Update PrologueScene**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
preload() {
|
||||||
|
// Detect language
|
||||||
|
const savedLang = localStorage.getItem('game_language') || 'sl-SI';
|
||||||
|
const langShort = savedLang.split('-')[0];
|
||||||
|
|
||||||
|
// Load localization
|
||||||
|
this.load.json(`lang_${savedLang}`, `assets/localization/${savedLang}.json`);
|
||||||
|
|
||||||
|
// Load character portraits
|
||||||
|
this.load.image('kai_portrait', 'reference_images/kai_master_style33.png');
|
||||||
|
this.load.image('ana_portrait', 'reference_images/ana_master_style33.png');
|
||||||
|
|
||||||
|
// Load voiceovers for current language
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
const num = i.toString().padStart(2, '0');
|
||||||
|
this.load.audio(
|
||||||
|
`prologue_${num}`,
|
||||||
|
`assets/audio 🔴/voiceover/prologue_${langShort}/prologue_${num}.wav`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
// Initialize localization
|
||||||
|
this.lang = new LocalizationManager(this.game);
|
||||||
|
this.lang.loadLanguage(savedLang);
|
||||||
|
|
||||||
|
// Use translations
|
||||||
|
const skipText = this.add.text(
|
||||||
|
width - 20, 20,
|
||||||
|
this.lang.getText('ui.skip'),
|
||||||
|
{ fontSize: '16px', color: '#888888' }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎬 AUTOMATED GENERATION WORKFLOW
|
||||||
|
|
||||||
|
### **Master Script:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# generate_all_languages.sh
|
||||||
|
|
||||||
|
echo "🌍 Generating voiceovers for all 6 languages..."
|
||||||
|
|
||||||
|
# Slovenian (DONE)
|
||||||
|
echo "✅ Slovenian - already complete"
|
||||||
|
|
||||||
|
# English
|
||||||
|
./ai_voice_gen/generate_prologue_english.sh
|
||||||
|
|
||||||
|
# German
|
||||||
|
./ai_voice_gen/generate_prologue_german.sh
|
||||||
|
|
||||||
|
# Italian
|
||||||
|
./ai_voice_gen/generate_prologue_italian.sh
|
||||||
|
|
||||||
|
# Croatian
|
||||||
|
./ai_voice_gen/generate_prologue_croatian.sh
|
||||||
|
|
||||||
|
# Serbian
|
||||||
|
./ai_voice_gen/generate_prologue_serbian.sh
|
||||||
|
|
||||||
|
echo "🎉 All languages generated!"
|
||||||
|
echo "📊 Total files: 72 (12 per language × 6 languages)"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Estimated Time:** ~20 minutes for all languages
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 PRIORITY ORDER
|
||||||
|
|
||||||
|
### **Immediate (This Month):**
|
||||||
|
1. ✅ Slovenian (COMPLETE)
|
||||||
|
2. **English** (biggest market)
|
||||||
|
|
||||||
|
### **High Priority (Next Month):**
|
||||||
|
3. **German** (Steam top 3 market)
|
||||||
|
4. **Italian** (neighboring country, big gaming market)
|
||||||
|
|
||||||
|
### **Medium Priority (Q1 2026):**
|
||||||
|
5. **Croatian** (region similarity)
|
||||||
|
6. **Serbian** (region similarity)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 NEXT STEPS
|
||||||
|
|
||||||
|
### **TODAY:**
|
||||||
|
1. Create `LocalizationManager.js`
|
||||||
|
2. Extract Slovenian text to `sl-SI.json`
|
||||||
|
3. Create `en-US.json` (English translation)
|
||||||
|
|
||||||
|
### **THIS WEEK:**
|
||||||
|
4. Generate English voiceovers (12 files)
|
||||||
|
5. Test language switching
|
||||||
|
6. Create language selector UI
|
||||||
|
|
||||||
|
### **NEXT WEEK:**
|
||||||
|
7. German + Italian translations
|
||||||
|
8. Generate voiceovers
|
||||||
|
9. Full integration test
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 NOTES
|
||||||
|
|
||||||
|
**Why These 5 Languages?**
|
||||||
|
1. **English** - Global standard, Steam #1
|
||||||
|
2. **German** - Steam #2 market, high-quality gaming culture
|
||||||
|
3. **Italian** - Close to Slovenia, big indie game market
|
||||||
|
4. **Croatian** - Regional, similar culture, easy translation
|
||||||
|
5. **Serbian** - Regional, similar culture, Cyrillic option
|
||||||
|
|
||||||
|
**Alternative Languages to Consider:**
|
||||||
|
- **Russian** (huge market, but Cyrillic)
|
||||||
|
- **Spanish** (global, but less indie focus)
|
||||||
|
- **French** (big market, strict translation requirements)
|
||||||
|
- **Polish** (huge gaming market, Slavic language)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ SUCCESS CRITERIA
|
||||||
|
|
||||||
|
- [ ] All 6 languages fully translated
|
||||||
|
- [ ] 72 voiceover files generated (12 × 6)
|
||||||
|
- [ ] Language selector UI functional
|
||||||
|
- [ ] Runtime switching works seamlessly
|
||||||
|
- [ ] No performance impact
|
||||||
|
- [ ] Saved preferences persist
|
||||||
|
- [ ] All text uses localization system
|
||||||
|
|
||||||
|
**Target Launch:** All 6 languages available at **Early Access launch**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated:** January 4, 2026
|
||||||
|
**Status:** Planning → Implementation Phase Starting
|
||||||
67
scripts/generate_all_languages.sh
Normal file
67
scripts/generate_all_languages.sh
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# MASTER SCRIPT - Generate ALL 4 languages tonight
|
||||||
|
# Run this ONE command and everything happens automatically!
|
||||||
|
|
||||||
|
echo "🌍 MULTI-LANGUAGE GENERATION - TONIGHT PRODUCTION"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
echo "Languages: English, German, Italian, Chinese"
|
||||||
|
echo "Files: 48 voiceovers (12 per language)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if DeepL key is set
|
||||||
|
if [ -z "$DEEPL_API_KEY" ]; then
|
||||||
|
echo "⚠️ Warning: DEEPL_API_KEY not set"
|
||||||
|
echo "Set it with: export DEEPL_API_KEY='your-key-here'"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 1: Extract Slovenian (if not done)
|
||||||
|
echo "📝 Step 1: Extracting Slovenian text..."
|
||||||
|
if [ ! -f "assets/localization/sl-SI.json" ]; then
|
||||||
|
python3 scripts/extract_slovenian.py
|
||||||
|
echo "✅ Slovenian extracted"
|
||||||
|
else
|
||||||
|
echo "✅ Slovenian already exists"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 2: Translate to 4 languages
|
||||||
|
echo "🔄 Step 2: Translating to 4 languages..."
|
||||||
|
python3 scripts/translate_all.py
|
||||||
|
echo "✅ Translations complete"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 3: Generate voiceovers
|
||||||
|
echo "🎤 Step 3: Generating voiceovers..."
|
||||||
|
|
||||||
|
echo " 🇬🇧 Generating English..."
|
||||||
|
./ai_voice_gen/generate_prologue_english.sh > /dev/null 2>&1
|
||||||
|
echo " ✅ English: 12 files"
|
||||||
|
|
||||||
|
echo " 🇩🇪 Generating German..."
|
||||||
|
./ai_voice_gen/generate_prologue_german.sh > /dev/null 2>&1
|
||||||
|
echo " ✅ German: 12 files"
|
||||||
|
|
||||||
|
echo " 🇮🇹 Generating Italian..."
|
||||||
|
./ai_voice_gen/generate_prologue_italian.sh > /dev/null 2>&1
|
||||||
|
echo " ✅ Italian: 12 files"
|
||||||
|
|
||||||
|
echo " 🇨🇳 Generating Chinese..."
|
||||||
|
./ai_voice_gen/generate_prologue_chinese.sh > /dev/null 2>&1
|
||||||
|
echo " ✅ Chinese: 12 files"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🎉 ALL LANGUAGES COMPLETE!"
|
||||||
|
echo ""
|
||||||
|
echo "📊 Summary:"
|
||||||
|
echo " - 5 languages total (including Slovenian)"
|
||||||
|
echo " - 60 voiceover files (12 × 5)"
|
||||||
|
echo " - 5 JSON localization files"
|
||||||
|
echo ""
|
||||||
|
echo "📁 Files created:"
|
||||||
|
ls -lh assets/localization/*.json | awk '{print " ", $9, "(" $5 ")"}'
|
||||||
|
echo ""
|
||||||
|
du -sh assets/audio\ 🔴/voiceover/prologue_* | awk '{print " ", $2, "(" $1 ")"}'
|
||||||
|
echo ""
|
||||||
|
echo "✅ Ready to commit & push!"
|
||||||
Reference in New Issue
Block a user