@zigrivers/scaffold 3.4.1 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -0
- package/content/knowledge/game/game-accessibility.md +328 -0
- package/content/knowledge/game/game-ai-patterns.md +567 -0
- package/content/knowledge/game/game-asset-pipeline.md +363 -0
- package/content/knowledge/game/game-audio-design.md +344 -0
- package/content/knowledge/game/game-binary-vcs-strategy.md +396 -0
- package/content/knowledge/game/game-design-document.md +269 -0
- package/content/knowledge/game/game-domain-patterns.md +299 -0
- package/content/knowledge/game/game-economy-design.md +355 -0
- package/content/knowledge/game/game-engine-selection.md +242 -0
- package/content/knowledge/game/game-input-systems.md +379 -0
- package/content/knowledge/game/game-level-content-design.md +483 -0
- package/content/knowledge/game/game-liveops-analytics.md +280 -0
- package/content/knowledge/game/game-localization.md +323 -0
- package/content/knowledge/game/game-milestone-definitions.md +337 -0
- package/content/knowledge/game/game-modding-ugc.md +390 -0
- package/content/knowledge/game/game-narrative-design.md +404 -0
- package/content/knowledge/game/game-networking.md +393 -0
- package/content/knowledge/game/game-performance-budgeting.md +389 -0
- package/content/knowledge/game/game-platform-certification.md +417 -0
- package/content/knowledge/game/game-project-structure.md +360 -0
- package/content/knowledge/game/game-save-systems.md +452 -0
- package/content/knowledge/game/game-testing-strategy.md +470 -0
- package/content/knowledge/game/game-ui-patterns.md +477 -0
- package/content/knowledge/game/game-vr-ar-design.md +313 -0
- package/content/knowledge/review/review-art-bible.md +305 -0
- package/content/knowledge/review/review-game-design.md +303 -0
- package/content/knowledge/review/review-game-economy.md +272 -0
- package/content/knowledge/review/review-game-ui.md +293 -0
- package/content/knowledge/review/review-netcode.md +280 -0
- package/content/knowledge/review/review-platform-cert.md +341 -0
- package/content/methodology/custom-defaults.yml +25 -0
- package/content/methodology/deep.yml +25 -0
- package/content/methodology/game-overlay.yml +145 -0
- package/content/methodology/mvp.yml +25 -0
- package/content/pipeline/architecture/ai-behavior-design.md +87 -0
- package/content/pipeline/architecture/netcode-spec.md +86 -0
- package/content/pipeline/architecture/review-netcode.md +78 -0
- package/content/pipeline/foundation/performance-budgets.md +91 -0
- package/content/pipeline/modeling/narrative-bible.md +84 -0
- package/content/pipeline/pre/game-design-document.md +90 -0
- package/content/pipeline/pre/review-gdd.md +74 -0
- package/content/pipeline/quality/analytics-telemetry.md +98 -0
- package/content/pipeline/quality/live-ops-plan.md +99 -0
- package/content/pipeline/quality/platform-cert-prep.md +129 -0
- package/content/pipeline/quality/playtest-plan.md +84 -0
- package/content/pipeline/specification/art-bible.md +87 -0
- package/content/pipeline/specification/audio-design.md +97 -0
- package/content/pipeline/specification/content-structure-design.md +142 -0
- package/content/pipeline/specification/economy-design.md +105 -0
- package/content/pipeline/specification/game-accessibility.md +82 -0
- package/content/pipeline/specification/game-ui-spec.md +97 -0
- package/content/pipeline/specification/input-controls-spec.md +81 -0
- package/content/pipeline/specification/localization-plan.md +113 -0
- package/content/pipeline/specification/modding-ugc-spec.md +116 -0
- package/content/pipeline/specification/online-services-spec.md +104 -0
- package/content/pipeline/specification/review-economy.md +87 -0
- package/content/pipeline/specification/review-game-ui.md +73 -0
- package/content/pipeline/specification/save-system-spec.md +116 -0
- package/dist/cli/commands/adopt.d.ts.map +1 -1
- package/dist/cli/commands/adopt.js +25 -0
- package/dist/cli/commands/adopt.js.map +1 -1
- package/dist/cli/commands/adopt.test.js +28 -1
- package/dist/cli/commands/adopt.test.js.map +1 -1
- package/dist/cli/commands/build.test.js +3 -0
- package/dist/cli/commands/build.test.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +6 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.test.js +12 -1
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/commands/knowledge.test.js +8 -0
- package/dist/cli/commands/knowledge.test.js.map +1 -1
- package/dist/cli/commands/next.d.ts.map +1 -1
- package/dist/cli/commands/next.js +19 -5
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/next.test.js +56 -0
- package/dist/cli/commands/next.test.js.map +1 -1
- package/dist/cli/commands/rework.d.ts.map +1 -1
- package/dist/cli/commands/rework.js +11 -2
- package/dist/cli/commands/rework.js.map +1 -1
- package/dist/cli/commands/rework.test.js +5 -0
- package/dist/cli/commands/rework.test.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +54 -4
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/run.test.js +384 -0
- package/dist/cli/commands/run.test.js.map +1 -1
- package/dist/cli/commands/skip.test.js +3 -0
- package/dist/cli/commands/skip.test.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +16 -3
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/status.test.js +55 -0
- package/dist/cli/commands/status.test.js.map +1 -1
- package/dist/cli/output/auto.d.ts +3 -0
- package/dist/cli/output/auto.d.ts.map +1 -1
- package/dist/cli/output/auto.js +9 -0
- package/dist/cli/output/auto.js.map +1 -1
- package/dist/cli/output/context.d.ts +6 -0
- package/dist/cli/output/context.d.ts.map +1 -1
- package/dist/cli/output/context.js.map +1 -1
- package/dist/cli/output/context.test.js +87 -0
- package/dist/cli/output/context.test.js.map +1 -1
- package/dist/cli/output/error-display.test.js +3 -0
- package/dist/cli/output/error-display.test.js.map +1 -1
- package/dist/cli/output/interactive.d.ts +3 -0
- package/dist/cli/output/interactive.d.ts.map +1 -1
- package/dist/cli/output/interactive.js +76 -0
- package/dist/cli/output/interactive.js.map +1 -1
- package/dist/cli/output/json.d.ts +3 -0
- package/dist/cli/output/json.d.ts.map +1 -1
- package/dist/cli/output/json.js +9 -0
- package/dist/cli/output/json.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +3 -2
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +641 -15
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +26 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/config/schema.test.js +192 -1
- package/dist/config/schema.test.js.map +1 -1
- package/dist/core/assembly/overlay-loader.d.ts +24 -0
- package/dist/core/assembly/overlay-loader.d.ts.map +1 -0
- package/dist/core/assembly/overlay-loader.js +190 -0
- package/dist/core/assembly/overlay-loader.js.map +1 -0
- package/dist/core/assembly/overlay-loader.test.d.ts +2 -0
- package/dist/core/assembly/overlay-loader.test.d.ts.map +1 -0
- package/dist/core/assembly/overlay-loader.test.js +106 -0
- package/dist/core/assembly/overlay-loader.test.js.map +1 -0
- package/dist/core/assembly/overlay-resolver.d.ts +15 -0
- package/dist/core/assembly/overlay-resolver.d.ts.map +1 -0
- package/dist/core/assembly/overlay-resolver.js +58 -0
- package/dist/core/assembly/overlay-resolver.js.map +1 -0
- package/dist/core/assembly/overlay-resolver.test.d.ts +2 -0
- package/dist/core/assembly/overlay-resolver.test.d.ts.map +1 -0
- package/dist/core/assembly/overlay-resolver.test.js +246 -0
- package/dist/core/assembly/overlay-resolver.test.js.map +1 -0
- package/dist/core/assembly/overlay-state-resolver.d.ts +26 -0
- package/dist/core/assembly/overlay-state-resolver.d.ts.map +1 -0
- package/dist/core/assembly/overlay-state-resolver.js +63 -0
- package/dist/core/assembly/overlay-state-resolver.js.map +1 -0
- package/dist/core/assembly/overlay-state-resolver.test.d.ts +2 -0
- package/dist/core/assembly/overlay-state-resolver.test.d.ts.map +1 -0
- package/dist/core/assembly/overlay-state-resolver.test.js +256 -0
- package/dist/core/assembly/overlay-state-resolver.test.js.map +1 -0
- package/dist/core/assembly/preset-loader.d.ts +1 -0
- package/dist/core/assembly/preset-loader.d.ts.map +1 -1
- package/dist/core/assembly/preset-loader.js +2 -0
- package/dist/core/assembly/preset-loader.js.map +1 -1
- package/dist/core/dependency/eligibility.test.js +3 -0
- package/dist/core/dependency/eligibility.test.js.map +1 -1
- package/dist/e2e/game-pipeline.test.d.ts +10 -0
- package/dist/e2e/game-pipeline.test.d.ts.map +1 -0
- package/dist/e2e/game-pipeline.test.js +298 -0
- package/dist/e2e/game-pipeline.test.js.map +1 -0
- package/dist/e2e/init.test.js +3 -0
- package/dist/e2e/init.test.js.map +1 -1
- package/dist/project/adopt.d.ts +3 -1
- package/dist/project/adopt.d.ts.map +1 -1
- package/dist/project/adopt.js +29 -1
- package/dist/project/adopt.js.map +1 -1
- package/dist/project/adopt.test.js +51 -1
- package/dist/project/adopt.test.js.map +1 -1
- package/dist/types/config.d.ts +50 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.test.d.ts +2 -0
- package/dist/types/config.test.d.ts.map +1 -0
- package/dist/types/config.test.js +97 -0
- package/dist/types/config.test.js.map +1 -0
- package/dist/utils/eligible.d.ts +3 -2
- package/dist/utils/eligible.d.ts.map +1 -1
- package/dist/utils/eligible.js +18 -4
- package/dist/utils/eligible.js.map +1 -1
- package/dist/utils/errors.d.ts +4 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +31 -0
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/errors.test.js +4 -1
- package/dist/utils/errors.test.js.map +1 -1
- package/dist/wizard/questions.d.ts +4 -0
- package/dist/wizard/questions.d.ts.map +1 -1
- package/dist/wizard/questions.js +59 -1
- package/dist/wizard/questions.js.map +1 -1
- package/dist/wizard/questions.test.js +178 -4
- package/dist/wizard/questions.test.js.map +1 -1
- package/dist/wizard/wizard.d.ts +1 -0
- package/dist/wizard/wizard.d.ts.map +1 -1
- package/dist/wizard/wizard.js +4 -1
- package/dist/wizard/wizard.js.map +1 -1
- package/dist/wizard/wizard.test.js +102 -4
- package/dist/wizard/wizard.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-liveops-analytics
|
|
3
|
+
description: Data taxonomy, telemetry pipelines, A/B testing, content cadence, seasonal events, post-launch support, and KPI-driven decision making
|
|
4
|
+
topics: [game-dev, analytics, liveops, telemetry, kpi, ab-testing]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Live operations (LiveOps) and analytics transform a game from a one-time product into a continuously evolving service. The core discipline is building feedback loops: instrument player behavior, analyze the data, form hypotheses, ship changes, measure results. Without robust telemetry and a clear KPI hierarchy, LiveOps teams operate blind — making content decisions based on gut feel, missing retention cliffs, and shipping events that move no needle. Games that invest in data infrastructure from early production gain a compounding advantage: every content update is informed by the last, every A/B test sharpens understanding of the player base, and every seasonal event builds on measured engagement patterns.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
### Data Taxonomy and KPI Hierarchy
|
|
12
|
+
|
|
13
|
+
Game analytics requires a structured taxonomy that separates vanity metrics from actionable KPIs. The hierarchy flows from business health (revenue, growth) down to behavioral signals (progression, session patterns).
|
|
14
|
+
|
|
15
|
+
**Top-Level Health Metrics:**
|
|
16
|
+
- **DAU / MAU** — Daily and Monthly Active Users; the MAU/DAU ratio (stickiness) reveals whether players return habitually or sporadically
|
|
17
|
+
- **D1 / D7 / D30 Retention** — Percentage of new users returning after 1, 7, and 30 days; the single most important metric for predicting long-term viability
|
|
18
|
+
- **ARPDAU** — Average Revenue Per Daily Active User; revenue efficiency independent of install volume
|
|
19
|
+
- **LTV** — Lifetime Value; total revenue a player generates before churning; must exceed Customer Acquisition Cost (CAC) by 3x+ for sustainable growth
|
|
20
|
+
- **Conversion Rate** — Percentage of free players who make any purchase; typical F2P range is 2-5%
|
|
21
|
+
|
|
22
|
+
**Mid-Level Engagement Metrics:**
|
|
23
|
+
- **Session Length** — Average time per play session; declining session length is an early churn signal
|
|
24
|
+
- **Sessions Per Day** — Frequency of return within a single day; driven by energy systems, daily rewards, social obligations
|
|
25
|
+
- **Progression Velocity** — How fast players advance through content; too fast causes content drought, too slow causes frustration drop-off
|
|
26
|
+
- **Feature Adoption Rate** — Percentage of eligible players who engage with a new feature within 7 days of exposure
|
|
27
|
+
|
|
28
|
+
**Behavioral Signals:**
|
|
29
|
+
- **Funnel Drop-Off** — Where players abandon a sequence (tutorial, purchase flow, onboarding); each step should retain 85%+ of the previous step
|
|
30
|
+
- **Content Completion Rate** — Percentage of players who finish a level, quest, or event; signals difficulty calibration
|
|
31
|
+
- **Social Actions** — Friend adds, guild joins, co-op sessions; social bonds are the strongest retention predictor
|
|
32
|
+
- **Error / Crash Rate** — Technical failures per session; crashes in the first 5 minutes destroy D1 retention
|
|
33
|
+
|
|
34
|
+
### Content Cadence and Seasonal Events
|
|
35
|
+
|
|
36
|
+
LiveOps calendars follow predictable rhythms that align with player expectations and real-world events:
|
|
37
|
+
|
|
38
|
+
- **Weekly**: Rotating challenges, leaderboard resets, limited-time modes
|
|
39
|
+
- **Bi-weekly**: New content drops (characters, maps, items) to sustain engagement between major updates
|
|
40
|
+
- **Monthly**: Season passes or battle passes with a progression track; ~28-day duration with 2-3 day overlap for late completionists
|
|
41
|
+
- **Quarterly**: Major content updates (new regions, story chapters, mechanical expansions)
|
|
42
|
+
- **Seasonal**: Holiday events (Halloween, Lunar New Year, summer) with themed cosmetics and limited-time mechanics
|
|
43
|
+
|
|
44
|
+
Each content beat should have a clear engagement target and revenue hypothesis before development begins.
|
|
45
|
+
|
|
46
|
+
### A/B Testing Pipeline
|
|
47
|
+
|
|
48
|
+
A/B testing in games requires careful population segmentation to avoid contaminating the experience of players who interact with each other (e.g., different prices in a shared economy).
|
|
49
|
+
|
|
50
|
+
## Deep Guidance
|
|
51
|
+
|
|
52
|
+
### Telemetry Architecture
|
|
53
|
+
|
|
54
|
+
A production telemetry pipeline has four layers: instrumentation, ingestion, processing, and visualization. Each layer must handle the scale of a live game — millions of events per minute at peak.
|
|
55
|
+
|
|
56
|
+
**Instrumentation Layer:**
|
|
57
|
+
|
|
58
|
+
Every telemetry event should follow a consistent schema. Define a base event envelope that every event extends:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"event_id": "uuid-v4",
|
|
63
|
+
"event_name": "level_complete",
|
|
64
|
+
"timestamp": "2026-01-15T14:32:01.442Z",
|
|
65
|
+
"client_version": "2.4.1",
|
|
66
|
+
"platform": "ios",
|
|
67
|
+
"device_model": "iPhone15,2",
|
|
68
|
+
"user_id": "player_abc123",
|
|
69
|
+
"session_id": "sess_def456",
|
|
70
|
+
"properties": {
|
|
71
|
+
"level_id": "world3_stage7",
|
|
72
|
+
"duration_seconds": 142,
|
|
73
|
+
"deaths": 3,
|
|
74
|
+
"score": 28400,
|
|
75
|
+
"items_used": ["health_potion", "speed_boost"],
|
|
76
|
+
"difficulty": "normal"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Instrumentation rules:
|
|
82
|
+
- Every event gets a UUID, ISO-8601 timestamp, client version, platform, and session ID — no exceptions
|
|
83
|
+
- Property names use snake_case; values use consistent types (never mix string "3" with integer 3)
|
|
84
|
+
- Batch events client-side and flush every 30 seconds or when the batch reaches 50 events, whichever comes first
|
|
85
|
+
- Buffer events to local storage during offline play; flush when connectivity returns
|
|
86
|
+
- Never log personally identifiable information (PII) in telemetry — hash or anonymize user identifiers
|
|
87
|
+
- Tag events with the current A/B test assignments so every analysis can be segmented by experiment
|
|
88
|
+
|
|
89
|
+
**Ingestion Layer:**
|
|
90
|
+
|
|
91
|
+
Use a message queue (Kafka, AWS Kinesis, Google Pub/Sub) to decouple event producers from consumers. This absorbs traffic spikes during peak hours and event launches without dropping data.
|
|
92
|
+
|
|
93
|
+
Design for at-least-once delivery. Events may arrive duplicated; deduplication happens in the processing layer using event_id. Design ingestion endpoints to accept gzip-compressed payloads — mobile clients on cellular networks send 60-80% less data when compressed.
|
|
94
|
+
|
|
95
|
+
**Processing Layer:**
|
|
96
|
+
|
|
97
|
+
Raw events flow into a data lake (S3, GCS) partitioned by date and event name. A streaming processor (Apache Flink, Spark Streaming, or a simpler Lambda/Cloud Function pipeline) handles:
|
|
98
|
+
|
|
99
|
+
1. **Deduplication** — Remove events with duplicate event_id values
|
|
100
|
+
2. **Enrichment** — Join with user profile data (install date, country, cohort, spending tier)
|
|
101
|
+
3. **Aggregation** — Compute real-time metrics (concurrent users, revenue per minute, error rates)
|
|
102
|
+
4. **Alerting** — Trigger alerts when metrics breach thresholds (crash rate > 2%, revenue drops > 20% hour-over-hour)
|
|
103
|
+
|
|
104
|
+
**Visualization Layer:**
|
|
105
|
+
|
|
106
|
+
Dashboards should be organized by audience:
|
|
107
|
+
- **Executive dashboard**: DAU, revenue, D1/D7/D30 retention, top-line conversion — updated daily
|
|
108
|
+
- **LiveOps dashboard**: Event participation, content completion, store performance — updated hourly
|
|
109
|
+
- **Engineering dashboard**: Crash rates, API latency, matchmaking queue times, server load — real-time
|
|
110
|
+
- **Game design dashboard**: Progression funnels, difficulty curves, economy flow rates — updated daily
|
|
111
|
+
|
|
112
|
+
### Progression Funnel Analysis
|
|
113
|
+
|
|
114
|
+
The most actionable analysis in game analytics is funnel tracking through key progression milestones. Every game has a "critical path" — the sequence of actions a player must complete to reach the core loop.
|
|
115
|
+
|
|
116
|
+
Example funnel for a mobile RPG:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Stage | % of Installs | Drop-off
|
|
120
|
+
─────────────────────────┼───────────────┼─────────
|
|
121
|
+
App opened | 100% | —
|
|
122
|
+
Tutorial started | 95% | 5%
|
|
123
|
+
Tutorial completed | 72% | 23% ← RED FLAG
|
|
124
|
+
First battle won | 68% | 4%
|
|
125
|
+
Reached town hub | 61% | 7%
|
|
126
|
+
Equipped first item | 54% | 7%
|
|
127
|
+
Completed Chapter 1 | 41% | 13%
|
|
128
|
+
First IAP prompt seen | 38% | 3%
|
|
129
|
+
First IAP purchased | 4.2% | 33.8%
|
|
130
|
+
Reached Chapter 3 | 22% | 16%
|
|
131
|
+
Joined a guild | 12% | 10%
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Red flag analysis: A 23% drop-off during tutorial is critical. Investigate by segmenting:
|
|
135
|
+
- By platform (iOS vs Android) — Android devices have wider performance variance; tutorial may stutter on low-end hardware
|
|
136
|
+
- By acquisition source — Players from rewarded ads have lower intent than organic installs
|
|
137
|
+
- By tutorial step — Identify the exact screen or interaction where players quit
|
|
138
|
+
- By session duration — Did they play for 10 seconds (never engaged) or 3 minutes (confused)?
|
|
139
|
+
|
|
140
|
+
Target benchmarks: Tutorial completion should be 80%+. If below 70%, the tutorial is broken, not the players.
|
|
141
|
+
|
|
142
|
+
### A/B Testing Methodology
|
|
143
|
+
|
|
144
|
+
A/B testing in games differs from web A/B testing in three critical ways:
|
|
145
|
+
|
|
146
|
+
1. **Social contamination** — Players talk. If Group A gets better rewards than Group B, players will notice and complain on forums. Segment tests to avoid visible inequality.
|
|
147
|
+
2. **Long feedback loops** — A web test shows results in hours. Game economy tests need 14-30 days to show downstream effects on retention and spending.
|
|
148
|
+
3. **State persistence** — You cannot easily "undo" a game economy change. If Group A received double gold for a week, reverting creates a perceived loss.
|
|
149
|
+
|
|
150
|
+
**Test design framework:**
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
# A/B Test Configuration Schema
|
|
154
|
+
class ABTest:
|
|
155
|
+
test_id: str # "spring_2026_pricing_v2"
|
|
156
|
+
hypothesis: str # "Lowering starter pack price from $4.99 to $2.99
|
|
157
|
+
# will increase conversion by >30% without
|
|
158
|
+
# reducing D30 ARPDAU"
|
|
159
|
+
primary_metric: str # "conversion_rate_d7"
|
|
160
|
+
secondary_metrics: list # ["arpdau_d30", "d7_retention", "iap_count_d30"]
|
|
161
|
+
guardrail_metrics: list # ["crash_rate", "session_length", "d1_retention"]
|
|
162
|
+
population: str # "new_users_after_2026-03-01"
|
|
163
|
+
allocation: dict # {"control": 50, "variant_a": 50}
|
|
164
|
+
min_sample_size: int # 10000 per arm (calculated for 80% power, 5% significance)
|
|
165
|
+
duration_days: int # 14
|
|
166
|
+
segment_exclusions: list # ["whales_ltv_over_500", "employees"]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Sample size calculation**: For a 5% baseline conversion rate and a minimum detectable effect of 20% relative (i.e., detecting a move from 5.0% to 6.0%), you need approximately 25,000 users per arm at 80% power and 95% confidence. Under-powered tests waste time — they run for weeks and produce inconclusive results.
|
|
170
|
+
|
|
171
|
+
**Guardrail metrics**: Every test must define guardrail metrics that auto-halt the test if breached. If a pricing test increases conversion but crashes D1 retention by 5%, the test should stop immediately regardless of the primary metric.
|
|
172
|
+
|
|
173
|
+
### Seasonal Event Design
|
|
174
|
+
|
|
175
|
+
Successful seasonal events follow a predictable structure:
|
|
176
|
+
|
|
177
|
+
**Pre-event (7-14 days before):**
|
|
178
|
+
- Tease event through in-game mail, loading screens, social media
|
|
179
|
+
- Update app store screenshots and feature graphics
|
|
180
|
+
- Pre-load event assets in a background download to avoid day-one download friction
|
|
181
|
+
- Verify server capacity for expected traffic spike (typically 1.5-3x normal DAU)
|
|
182
|
+
|
|
183
|
+
**Event runtime (7-28 days):**
|
|
184
|
+
- Clear event UI that shows progress, time remaining, and reward tiers
|
|
185
|
+
- Multiple engagement tracks: casual track (play normally, earn event currency), hardcore track (special challenges for exclusive rewards)
|
|
186
|
+
- Pacing curve: easy early milestones to hook participation, escalating effort toward the end
|
|
187
|
+
- Mid-event content drop (new challenges, bonus multiplier) to re-engage players who stalled
|
|
188
|
+
- Daily login bonus specific to the event to maintain return frequency
|
|
189
|
+
|
|
190
|
+
**Post-event (3-7 days after):**
|
|
191
|
+
- Grace period for players to spend remaining event currency
|
|
192
|
+
- Event recap (your stats, leaderboard rank, rewards earned)
|
|
193
|
+
- Remove event UI but keep earned items/cosmetics permanently
|
|
194
|
+
- Publish event retrospective internally: participation rate, revenue lift, retention impact, what worked, what didn't
|
|
195
|
+
|
|
196
|
+
**Revenue integration**: Seasonal events are the highest-revenue windows. Offer event-exclusive bundles, a paid event pass (premium track), and limited-time cosmetics. Price anchoring: show a "full value" price crossed out next to the bundle price. Time pressure ("3 days remaining") drives conversion.
|
|
197
|
+
|
|
198
|
+
### Server Maintenance Communication
|
|
199
|
+
|
|
200
|
+
Planned maintenance communication follows a strict timeline:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
T-72h — First announcement: in-game banner, website, social media, Discord
|
|
204
|
+
T-24h — Reminder with exact time, expected duration, and timezone conversions
|
|
205
|
+
T-4h — Final reminder; disable new matchmaking / long-duration activities
|
|
206
|
+
T-1h — Persistent in-game popup: "Maintenance in 60 minutes. Save your progress."
|
|
207
|
+
T-15m — Force-save all player state; prevent new session starts
|
|
208
|
+
T-0 — Servers go down; redirect all clients to maintenance screen with ETA
|
|
209
|
+
T+done — Servers up; push notification: "We're back! Log in for compensation reward"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Always over-estimate downtime publicly. If maintenance takes 2 hours, announce 4 hours. Finishing early feels like a gift; running late feels like incompetence.
|
|
213
|
+
|
|
214
|
+
**Compensation formula**: For every hour of unplanned downtime, grant premium currency equal to 1 hour of median free-player earning rate. For planned maintenance during announced windows, compensation is optional but goodwill-positive — a small gift (stamina refill, daily reward chest) keeps sentiment positive.
|
|
215
|
+
|
|
216
|
+
### Post-Launch Support Workflow
|
|
217
|
+
|
|
218
|
+
Post-launch LiveOps follows a weekly cadence:
|
|
219
|
+
|
|
220
|
+
**Monday**: Review weekend metrics (weekends are peak). Identify anomalies. Prioritize issues.
|
|
221
|
+
|
|
222
|
+
**Tuesday-Wednesday**: Ship hotfixes for critical bugs. Deploy content updates. Activate weekly events.
|
|
223
|
+
|
|
224
|
+
**Thursday**: A/B test analysis meeting. Review running tests, check for significance, decide on early stops.
|
|
225
|
+
|
|
226
|
+
**Friday**: Plan next week's content. Approve store rotations. Draft social media calendar.
|
|
227
|
+
|
|
228
|
+
**Continuous**: Monitor real-time dashboards for crash spikes, revenue anomalies, and exploit reports. On-call rotation covers evenings and weekends.
|
|
229
|
+
|
|
230
|
+
### Economy Health Monitoring
|
|
231
|
+
|
|
232
|
+
A game economy requires continuous monitoring to detect inflation, deflation, and exploit-driven imbalances:
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
# Economy Health Dashboard Alerts
|
|
236
|
+
alerts:
|
|
237
|
+
- name: currency_inflation
|
|
238
|
+
metric: avg_soft_currency_balance
|
|
239
|
+
condition: "> 2x baseline_30d_average"
|
|
240
|
+
severity: P1
|
|
241
|
+
action: "Investigate new currency sources; check for duplication exploits"
|
|
242
|
+
|
|
243
|
+
- name: sink_failure
|
|
244
|
+
metric: daily_currency_sink_rate
|
|
245
|
+
condition: "< 60% of daily_currency_source_rate"
|
|
246
|
+
severity: P2
|
|
247
|
+
action: "Economy is inflating; add or strengthen sinks"
|
|
248
|
+
|
|
249
|
+
- name: conversion_collapse
|
|
250
|
+
metric: iap_conversion_rate_d7
|
|
251
|
+
condition: "< 50% of trailing_30d_average"
|
|
252
|
+
severity: P0
|
|
253
|
+
action: "Immediate investigation; check store, pricing, paywall"
|
|
254
|
+
|
|
255
|
+
- name: whale_concentration
|
|
256
|
+
metric: top_1pct_revenue_share
|
|
257
|
+
condition: "> 70%"
|
|
258
|
+
severity: P2
|
|
259
|
+
action: "Revenue overly dependent on whales; diversify monetization"
|
|
260
|
+
|
|
261
|
+
- name: new_user_economy
|
|
262
|
+
metric: d3_soft_currency_median
|
|
263
|
+
condition: "< tutorial_cost * 0.5"
|
|
264
|
+
severity: P1
|
|
265
|
+
action: "New players cannot afford basic upgrades; increase early grants"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Sink-source balance**: Track every currency source (quest rewards, daily login, event prizes, IAP) and every currency sink (upgrades, gacha pulls, cosmetics, energy refills). Plot the net flow daily. A healthy economy has sinks consuming 70-90% of generated currency, with the remaining 10-30% accumulating as player savings that create investment and loss aversion.
|
|
269
|
+
|
|
270
|
+
### Cohort Analysis
|
|
271
|
+
|
|
272
|
+
Never look at aggregate metrics alone. Always segment by cohort:
|
|
273
|
+
|
|
274
|
+
- **Install date cohort** — D30 retention for January installs vs February installs reveals whether game changes helped or hurt
|
|
275
|
+
- **Spending tier cohort** — Free, minnow ($1-$10 LTV), dolphin ($10-$100 LTV), whale ($100+ LTV) behave completely differently
|
|
276
|
+
- **Acquisition source cohort** — Organic installs have 2-3x better retention than paid installs from rewarded ad networks
|
|
277
|
+
- **Platform cohort** — iOS players typically have 1.5-2x higher ARPDAU than Android players
|
|
278
|
+
- **Geography cohort** — Tier-1 markets (US, UK, Japan, Korea) have radically different spending patterns than Tier-3 markets
|
|
279
|
+
|
|
280
|
+
A metric moving in aggregate can mask opposite movements in sub-populations. DAU can be flat while D1 retention drops 10% — because a marketing campaign is backfilling with low-quality installs at the same rate as churn.
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-localization
|
|
3
|
+
description: String management, font atlas pipeline, text expansion, subtitle standards, VO localization, culturalization, and LQA methodology
|
|
4
|
+
topics: [game-dev, localization, l10n, lqa, fonts, rtl]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Game localization is not translation — it is the engineering and cultural adaptation required to make a game feel native in every target market. A translated string that does not fit the UI, a font that cannot render Chinese characters, a gesture that is offensive in Brazil, or a subtitle that flashes too fast for reading speed norms — each of these failures breaks immersion and signals to the player that they are an afterthought. Localization touches every layer of the stack: string management, rendering, audio, UI layout, cultural review, and QA. The cost of retrofitting localization into a game that was not designed for it is 3-5x higher than building it in from the start.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
### String Management Systems
|
|
12
|
+
|
|
13
|
+
All player-facing text must be externalized into string tables, never hardcoded. The string management pipeline has three components: authoring (developers write string IDs), translation (translators produce localized variants), and integration (the game loads the correct variant at runtime).
|
|
14
|
+
|
|
15
|
+
**String ID conventions:**
|
|
16
|
+
- Use hierarchical, descriptive IDs: `ui.main_menu.play_button`, `dialogue.npc_blacksmith.greeting_01`
|
|
17
|
+
- Never use the English text as the key — English text changes during development, breaking all translations
|
|
18
|
+
- Prefix system strings vs content strings: `sys.error.connection_lost` vs `content.quest.dragon_slayer.desc`
|
|
19
|
+
- Include context hints in comments: `/* Button label, max 12 chars */` helps translators make appropriate choices
|
|
20
|
+
|
|
21
|
+
**Text expansion rules by language:**
|
|
22
|
+
- English (source) → German: +30% average, up to +50% for short strings
|
|
23
|
+
- English → Finnish: +30-40%
|
|
24
|
+
- English → French: +15-20%
|
|
25
|
+
- English → Spanish: +15-25%
|
|
26
|
+
- English → Japanese: -10-30% (fewer characters but may need more vertical space)
|
|
27
|
+
- English → Chinese (Simplified): -30-50% in character count but wider individual glyphs
|
|
28
|
+
- English → Korean: -10-20% character count
|
|
29
|
+
- English → Arabic/Hebrew (RTL): Similar length but requires full layout mirroring
|
|
30
|
+
|
|
31
|
+
UI must accommodate the worst-case expansion. A button designed to fit "Play" (4 chars) must also fit "Spielen" (7 chars, German) without truncation or overflow.
|
|
32
|
+
|
|
33
|
+
### Font Atlas and Rendering
|
|
34
|
+
|
|
35
|
+
Latin-alphabet games can use a single font atlas with 200-300 glyphs. CJK (Chinese, Japanese, Korean) localization requires thousands of glyphs, fundamentally changing the font rendering strategy.
|
|
36
|
+
|
|
37
|
+
**CJK considerations:**
|
|
38
|
+
- Japanese requires ~2,200 Joyo kanji + hiragana + katakana (~3,000 glyphs minimum)
|
|
39
|
+
- Chinese Simplified requires ~6,500 common characters (GB2312 set) for full coverage
|
|
40
|
+
- Korean Hangul has 11,172 possible syllable blocks; pre-composed sets of ~2,500 cover 99% of text
|
|
41
|
+
- Static font atlases at this scale consume 16-64 MB of texture memory
|
|
42
|
+
- Dynamic font rendering (runtime rasterization with caching) is preferred for CJK — render glyphs on demand and cache to atlas
|
|
43
|
+
|
|
44
|
+
**RTL (Right-to-Left) languages:**
|
|
45
|
+
- Arabic and Hebrew text flows right-to-left, but numbers and Latin text embedded within flow left-to-right (bidirectional text)
|
|
46
|
+
- UI layouts must mirror: scrollbars move to the left, progress bars fill right-to-left, navigation reverses
|
|
47
|
+
- Arabic requires contextual shaping — each letter has up to 4 forms depending on position (initial, medial, final, isolated)
|
|
48
|
+
- Arabic text cannot simply be reversed string — a shaping engine (HarfBuzz, ICU) must process it
|
|
49
|
+
|
|
50
|
+
### Subtitle and Caption Standards
|
|
51
|
+
|
|
52
|
+
Subtitle presentation has measurable impact on comprehension and player experience. Industry standards from film and broadcast apply, with game-specific additions.
|
|
53
|
+
|
|
54
|
+
## Deep Guidance
|
|
55
|
+
|
|
56
|
+
### String Extraction and Translation Pipeline
|
|
57
|
+
|
|
58
|
+
The localization pipeline begins with string extraction and ends with integrated, tested builds in every supported language.
|
|
59
|
+
|
|
60
|
+
**Step 1: String extraction**
|
|
61
|
+
|
|
62
|
+
All strings live in a structured format that supports translator context:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"strings": [
|
|
67
|
+
{
|
|
68
|
+
"id": "ui.hud.health_label",
|
|
69
|
+
"source": "Health",
|
|
70
|
+
"context": "HUD label next to health bar. Max 10 characters.",
|
|
71
|
+
"max_length": 10,
|
|
72
|
+
"tags": ["ui", "hud"],
|
|
73
|
+
"screenshot": "assets/loc_screenshots/hud_health.png"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "ui.shop.buy_button",
|
|
77
|
+
"source": "Buy Now",
|
|
78
|
+
"context": "Purchase button in item shop. Should convey urgency.",
|
|
79
|
+
"max_length": 15,
|
|
80
|
+
"tags": ["ui", "shop", "monetization"],
|
|
81
|
+
"screenshot": "assets/loc_screenshots/shop_buy.png"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "dialogue.guard.warning_01",
|
|
85
|
+
"source": "Halt! No one passes without the captain's seal.",
|
|
86
|
+
"context": "Spoken by gate guard NPC. Stern, military tone.",
|
|
87
|
+
"max_length": null,
|
|
88
|
+
"tags": ["dialogue", "npc"],
|
|
89
|
+
"voice_acted": true,
|
|
90
|
+
"character": "Guard Captain Aldric"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Step 2: Translation Management System (TMS)**
|
|
97
|
+
|
|
98
|
+
Use a TMS (Crowdin, Lokalise, Phrase, memoQ) rather than spreadsheets. TMS platforms provide:
|
|
99
|
+
- Translation memory (TM) — previously translated strings are suggested automatically, ensuring consistency and reducing cost
|
|
100
|
+
- Glossary enforcement — key terms (character names, game mechanics, UI labels) are locked to approved translations
|
|
101
|
+
- In-context editing — translators see the string alongside a screenshot of where it appears in-game
|
|
102
|
+
- Pseudo-localization — generates fake translations that simulate text expansion and character coverage for testing before real translations arrive
|
|
103
|
+
- Branch-aware workflows — translations track the development branch, merge with code, and flag conflicts
|
|
104
|
+
|
|
105
|
+
**Step 3: Integration and build**
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
#!/usr/bin/env bash
|
|
109
|
+
# loc-build.sh — Pull translations and build localized assets
|
|
110
|
+
set -euo pipefail
|
|
111
|
+
|
|
112
|
+
TMS_PROJECT_ID="${TMS_PROJECT_ID:?Set TMS_PROJECT_ID}"
|
|
113
|
+
SUPPORTED_LANGS=("en" "de" "fr" "es" "ja" "ko" "zh-Hans" "zh-Hant" "ar" "pt-BR" "ru")
|
|
114
|
+
|
|
115
|
+
echo "=== Pulling translations from TMS ==="
|
|
116
|
+
for lang in "${SUPPORTED_LANGS[@]}"; do
|
|
117
|
+
echo " Pulling ${lang}..."
|
|
118
|
+
tms-cli pull --project "$TMS_PROJECT_ID" \
|
|
119
|
+
--language "$lang" \
|
|
120
|
+
--output "assets/localization/${lang}.json" \
|
|
121
|
+
--format structured-json
|
|
122
|
+
done
|
|
123
|
+
|
|
124
|
+
echo "=== Validating translations ==="
|
|
125
|
+
for lang in "${SUPPORTED_LANGS[@]}"; do
|
|
126
|
+
echo " Validating ${lang}..."
|
|
127
|
+
# Check for missing translations
|
|
128
|
+
loc-validator check-completeness \
|
|
129
|
+
--source "assets/localization/en.json" \
|
|
130
|
+
--target "assets/localization/${lang}.json" \
|
|
131
|
+
--fail-on-missing
|
|
132
|
+
|
|
133
|
+
# Check max_length constraints
|
|
134
|
+
loc-validator check-length \
|
|
135
|
+
--target "assets/localization/${lang}.json" \
|
|
136
|
+
--fail-on-overflow
|
|
137
|
+
|
|
138
|
+
# Check for placeholder consistency ({name}, {count}, etc.)
|
|
139
|
+
loc-validator check-placeholders \
|
|
140
|
+
--source "assets/localization/en.json" \
|
|
141
|
+
--target "assets/localization/${lang}.json"
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
echo "=== Building font atlases ==="
|
|
145
|
+
for lang in "${SUPPORTED_LANGS[@]}"; do
|
|
146
|
+
font-builder build \
|
|
147
|
+
--language "$lang" \
|
|
148
|
+
--strings "assets/localization/${lang}.json" \
|
|
149
|
+
--output "assets/fonts/${lang}_atlas.png" \
|
|
150
|
+
--sdf-mode
|
|
151
|
+
done
|
|
152
|
+
|
|
153
|
+
echo "=== Localization build complete ==="
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Font Rendering Pipeline
|
|
157
|
+
|
|
158
|
+
For CJK languages, static pre-baked font atlases are impractical. The standard approach is a dynamic Signed Distance Field (SDF) font renderer:
|
|
159
|
+
|
|
160
|
+
1. **Pre-seed the atlas** — At load time, rasterize the 500 most common characters for the target language into an SDF texture atlas
|
|
161
|
+
2. **Runtime rasterization** — When the text renderer encounters a glyph not in the atlas, rasterize it from the TrueType/OpenType font file, generate the SDF, and pack it into the atlas
|
|
162
|
+
3. **Atlas management** — Use a shelf-packing algorithm. When the atlas fills (typically 2048x2048 or 4096x4096), evict least-recently-used glyphs
|
|
163
|
+
4. **Fallback fonts** — If the primary font lacks a glyph (e.g., a Latin font missing CJK characters), fall back to Noto Sans CJK or a platform system font
|
|
164
|
+
|
|
165
|
+
SDF fonts scale cleanly at any size without regeneration, support outlines and drop shadows in the shader, and consume less memory than bitmap fonts at equivalent quality.
|
|
166
|
+
|
|
167
|
+
**Memory budgets for font atlases:**
|
|
168
|
+
- Latin-only game: 1-2 MB (one 1024x1024 RGBA atlas)
|
|
169
|
+
- CJK support: 8-16 MB (one 4096x4096 atlas with dynamic packing)
|
|
170
|
+
- Full global language support including Arabic shaping: 16-32 MB
|
|
171
|
+
|
|
172
|
+
### RTL Implementation Guide
|
|
173
|
+
|
|
174
|
+
Right-to-left support requires changes at three levels: text rendering, UI layout, and content design.
|
|
175
|
+
|
|
176
|
+
**Text rendering:**
|
|
177
|
+
- Integrate a Unicode bidirectional algorithm (UAX #9) implementation — ICU or FriBidi
|
|
178
|
+
- The algorithm determines the correct visual order for mixed-direction text (Arabic words interspersed with English brand names and numbers)
|
|
179
|
+
- Arabic contextual shaping: use HarfBuzz or platform-native text shaping. Each Arabic letter changes form based on its neighbors. Simple string reversal produces garbage.
|
|
180
|
+
- Diacritical marks (tashkeel) in Arabic must be positioned correctly above/below base characters
|
|
181
|
+
|
|
182
|
+
**UI layout mirroring:**
|
|
183
|
+
- Horizontal layouts reverse: left-aligned text becomes right-aligned, left-margin becomes right-margin
|
|
184
|
+
- Navigation flows reverse: "next" arrows point left, "back" arrows point right
|
|
185
|
+
- Progress bars and sliders fill from right to left
|
|
186
|
+
- Scrollbars move to the left side
|
|
187
|
+
- Icons that convey direction (arrows, pointing hands) must be mirrored; icons that do not convey direction (a clock, a star) must NOT be mirrored
|
|
188
|
+
- Implement a layout direction flag (`isRTL`) that UI containers check when positioning children
|
|
189
|
+
|
|
190
|
+
**Exceptions to mirroring:**
|
|
191
|
+
- Phone number fields stay LTR (numbers are universal)
|
|
192
|
+
- Timestamps remain in local convention
|
|
193
|
+
- Media playback controls (play, fast-forward) are not mirrored — these are universal symbols
|
|
194
|
+
- Latin text within an RTL context keeps its LTR direction (handled by the bidi algorithm)
|
|
195
|
+
|
|
196
|
+
### Subtitle and Caption Standards
|
|
197
|
+
|
|
198
|
+
Subtitle presentation follows established readability guidelines:
|
|
199
|
+
|
|
200
|
+
**Timing:**
|
|
201
|
+
- Minimum display time: 1.5 seconds (even for very short text)
|
|
202
|
+
- Maximum display time: 7 seconds per subtitle block
|
|
203
|
+
- Reading speed: 15-20 characters per second for adults; 12-15 for children's games
|
|
204
|
+
- Gap between consecutive subtitles: minimum 0.25 seconds (allows the eye to register a change)
|
|
205
|
+
|
|
206
|
+
**Formatting:**
|
|
207
|
+
- Maximum 2 lines per subtitle block
|
|
208
|
+
- Maximum 42 characters per line (including spaces)
|
|
209
|
+
- Use sentence case, not ALL CAPS (all caps reduces readability by 10-15%)
|
|
210
|
+
- Speaker identification for off-screen characters: brackets or colored text
|
|
211
|
+
- Italics for off-screen dialogue, narration, or internal monologue
|
|
212
|
+
- Sound effect descriptions in square brackets for accessibility: `[explosion]`, `[footsteps approaching]`
|
|
213
|
+
|
|
214
|
+
**Positioning:**
|
|
215
|
+
- Default position: bottom-center of screen, above any HUD elements
|
|
216
|
+
- When a HUD element overlaps, subtitles shift upward dynamically
|
|
217
|
+
- For VR: subtitles are world-locked (not head-locked) at 2-3 meters from the player, slightly below eye level
|
|
218
|
+
- Speaker-specific positioning: in multiplayer or scenes with multiple speakers, position subtitles near the speaker
|
|
219
|
+
|
|
220
|
+
### Voice-Over Localization
|
|
221
|
+
|
|
222
|
+
VO localization is the most expensive and complex localization task. Two strategies exist:
|
|
223
|
+
|
|
224
|
+
**Full dubbing:**
|
|
225
|
+
- Record all dialogue in every target language
|
|
226
|
+
- Requires casting voice actors for each language — matching tone, age, and personality of the original performance
|
|
227
|
+
- Lip-sync must be re-targeted (a major animation cost) or the game uses faceless/masked characters to avoid the issue
|
|
228
|
+
- Cost: $0.30-$0.80 per word per language for professional studio recording
|
|
229
|
+
- Timeline: 4-8 weeks per language after scripts are locked
|
|
230
|
+
- Best for story-driven games (RPGs, adventure games) where VO is central to the experience
|
|
231
|
+
|
|
232
|
+
**Subtitles only (original VO):**
|
|
233
|
+
- Keep the original language VO; translate text only
|
|
234
|
+
- Dramatically cheaper and faster
|
|
235
|
+
- Players hear the original performance, which is often preferred for stylized games (anime-style, distinct cultural settings)
|
|
236
|
+
- Adequate for most indie and AA games, and for languages with smaller markets
|
|
237
|
+
|
|
238
|
+
**Hybrid approach:**
|
|
239
|
+
- Dub into the 3-5 largest markets (English, Japanese, French, German, Spanish) and subtitle the rest
|
|
240
|
+
- This is the AAA standard for cost-effective global reach
|
|
241
|
+
|
|
242
|
+
**VO production workflow:**
|
|
243
|
+
1. Lock dialogue scripts (no changes after this point without re-recording)
|
|
244
|
+
2. Provide translators with audio reference files so they hear the original delivery
|
|
245
|
+
3. Translators produce adapted scripts that match lip-sync timing where possible
|
|
246
|
+
4. Casting directors in each territory audition actors against original character profiles
|
|
247
|
+
5. Record in professional studios with game audio direction (context, emotion, pacing)
|
|
248
|
+
6. Integrate recorded audio, verify lip-sync, QA dialogue triggers
|
|
249
|
+
|
|
250
|
+
### Culturalization
|
|
251
|
+
|
|
252
|
+
Culturalization goes beyond translation to address cultural sensitivities:
|
|
253
|
+
|
|
254
|
+
**Content to review:**
|
|
255
|
+
- **Gestures**: Thumbs-up is offensive in parts of the Middle East; the OK hand sign is offensive in Brazil
|
|
256
|
+
- **Colors**: White symbolizes death/mourning in East Asia; red symbolizes luck in China but danger in Western cultures
|
|
257
|
+
- **Symbols**: Religious symbols, national flags, and political imagery require careful handling — some are legally restricted (German anti-Nazi laws, Chinese content restrictions)
|
|
258
|
+
- **Numbers**: 4 is unlucky in East Asia (sounds like "death" in Mandarin/Japanese); 13 is unlucky in Western cultures
|
|
259
|
+
- **Historical references**: Colonial, wartime, and territorial references can provoke strong reactions — consult regional specialists
|
|
260
|
+
- **Body exposure**: Standards vary drastically; Middle Eastern and Chinese markets have stricter modesty requirements
|
|
261
|
+
- **Gambling imagery**: Loot boxes, slot machines, and gacha mechanics face legal restrictions in Belgium, Netherlands, and increasingly other markets
|
|
262
|
+
|
|
263
|
+
**Rating board variations:**
|
|
264
|
+
- A game rated T (Teen) by ESRB may receive a different rating from PEGI, CERO (Japan), or GRAC (Korea) based on cultural sensitivity differences
|
|
265
|
+
- Blood color (red vs green), alcohol references, and sexual content have different thresholds per region
|
|
266
|
+
- Some markets require a separate content review authority (China's NPPA approval process can take 6+ months)
|
|
267
|
+
|
|
268
|
+
### Linguistic Quality Assurance (LQA)
|
|
269
|
+
|
|
270
|
+
LQA is dedicated testing of every localized build, performed by native speakers who are also gamers.
|
|
271
|
+
|
|
272
|
+
**LQA methodology:**
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
Phase 1: Text-in-context review (3-5 days per language)
|
|
276
|
+
- Play through the entire game in each language
|
|
277
|
+
- Flag: truncation, overflow, missing translations, placeholder errors
|
|
278
|
+
- Flag: tone/register mismatches (formal where casual is needed)
|
|
279
|
+
- Flag: inconsistent terminology (same item called different names)
|
|
280
|
+
- Flag: gender/number agreement errors in gendered languages
|
|
281
|
+
|
|
282
|
+
Phase 2: Audio review (2-3 days per dubbed language)
|
|
283
|
+
- Verify all VO lines trigger correctly
|
|
284
|
+
- Check lip-sync alignment
|
|
285
|
+
- Flag mispronunciations of character/place names
|
|
286
|
+
- Verify subtitle-to-audio synchronization
|
|
287
|
+
|
|
288
|
+
Phase 3: Functional review (1-2 days per language)
|
|
289
|
+
- Test text input (player names, chat) in each language's character set
|
|
290
|
+
- Test sorting (alphabetical order differs: Swedish å comes after z)
|
|
291
|
+
- Test date/time/number formatting (DD/MM vs MM/DD, comma vs period decimal)
|
|
292
|
+
- Test currency formatting ($1,000.00 vs 1.000,00 €)
|
|
293
|
+
|
|
294
|
+
Phase 4: Culturalization review (1-2 days per region)
|
|
295
|
+
- Review all visual content (textures, UI art, cutscenes) for cultural issues
|
|
296
|
+
- Verify map/territory representations do not trigger geopolitical disputes
|
|
297
|
+
- Check that monetization flows comply with local regulations
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Bug severity for localization:**
|
|
301
|
+
- **Critical**: Game crashes due to localization data; hard-coded English blocks progression
|
|
302
|
+
- **Major**: Truncated text hides gameplay information; wrong translation changes meaning
|
|
303
|
+
- **Minor**: Awkward phrasing; inconsistent but understandable terminology
|
|
304
|
+
- **Cosmetic**: Slightly imperfect formatting; minor spacing issues
|
|
305
|
+
|
|
306
|
+
### Pseudo-Localization for Early Testing
|
|
307
|
+
|
|
308
|
+
Before real translations are available, use pseudo-localization to catch localization bugs during development:
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
Original: "Health: {0}/{1}"
|
|
312
|
+
Pseudo-FR: "[Ĥéåļŧĥ: {0}/{1} ]"
|
|
313
|
+
Pseudo-AR: "[صحة: {0}/{1}]" (with RTL marker)
|
|
314
|
+
Pseudo-JP: "[ヘルス: {0}/{1}]"
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Pseudo-localization rules:
|
|
318
|
+
- Replace ASCII characters with accented Unicode equivalents (catches encoding bugs)
|
|
319
|
+
- Expand string length by 30-40% with padding (catches truncation bugs)
|
|
320
|
+
- Wrap strings in brackets `[...]` (catches hardcoded strings that were not externalized — they will not have brackets)
|
|
321
|
+
- Add RTL markers for Arabic pseudo-loc (catches layout mirroring issues)
|
|
322
|
+
|
|
323
|
+
Run pseudo-localized builds in CI. If any UI element overflows, truncates, or displays raw string IDs, the build should warn. This catches 80% of localization bugs before a single translator touches the project.
|