惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
Recent Announcements
Recent Announcements
雷峰网
雷峰网
Last Week in AI
Last Week in AI
I
InfoQ
Google DeepMind News
Google DeepMind News
GbyAI
GbyAI
The Cloudflare Blog
aimingoo的专栏
aimingoo的专栏
量子位
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
D
DataBreaches.Net
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
MyScale Blog
MyScale Blog
美团技术团队
V
V2EX
Jina AI
Jina AI
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
腾讯CDC
Vercel News
Vercel News
A
About on SuperTechFans
J
Java Code Geeks
Martin Fowler
Martin Fowler
V
Visual Studio Blog
博客园_首页
酷 壳 – CoolShell
酷 壳 – CoolShell
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
U
Unit 42
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
云风的 BLOG
云风的 BLOG
博客园 - 三生石上(FineUI控件)
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The GitHub Blog
The GitHub Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Steamworks Multilingual Metadata Management: From Manual Maintenance to Structured Workflow
Hagicode · 2026-05-09 · via DEV Community

Steamworks Multilingual Metadata Management: From Manual Maintenance to Structured Workflow

The Steam platform requires games to provide store descriptions in 28 languages. Traditional manual maintenance is inefficient and error-prone. This article introduces how to build a structured multilingual metadata management system through HagiCode, achieving an integrated workflow from content creation to export and release.

Background

The Steam platform requires games and applications to provide multilingual store descriptions, including fields like about (detailed description) and short_description (short description). For products released globally, localization content in 28 languages is typically required.

This sounds like a simple content management task, but when you actually start working on it, you discover there are more problems than you imagined.

First, the maintenance workload is enormous. 28 languages multiplied by 2 fields equals 56 content blocks that need to be managed. Manually switching languages for editing in the Steamworks website backend is indeed inefficient. Every content update requires repeating this process—it's painful to even talk about it.

Second, scattered content is difficult to manage. Multilingual content is typically scattered across different tools and documents, lacking a unified local storage format. Version control becomes difficult, and team collaboration is prone to errors. After all, scattered things are like scattered memories—when you want to find them, you can't.

Furthermore, DLC content and main application content management are siloed. If your game has multiple DLCs, each DLC needs to maintain multilingual content separately, and management complexity grows exponentially. It's like life—things pile up, and you don't know where to start cleaning up.

Finally, the export format is unintuitive. The JSON format required by Steamworks doesn't match human reading habits, making manual editing error-prone. After all, who wants to look at that dense JSON?

These were all problems we encountered during the actual development of the HagiCode project. As an AI coding tool for global development, we need to maintain complete multilingual content for the Steam platform. Traditional maintenance methods could no longer meet our needs, and we urgently needed a more efficient solution. Actually, there's no other way—we had to build it ourselves.

About HagiCode

The solution shared in this article comes from our practical experience in the HagiCode project. HagiCode is an AI coding tool that supports multiple AI providers and code editors. During development, we needed to maintain multilingual store content for the Steam platform, which drove us to build a structured metadata management system.

The multilingual metadata management solution shared in this article is exactly what we actually refined through trial and optimization during HagiCode development. If you find this solution valuable, it shows our engineering strength is pretty good—so HagiCode itself is worth paying attention to. After all, a tool that can solve problems is a good tool, right?

Core Concepts

Languages and Fields

Steamworks supports a fairly complete list of languages, covering major markets:

en-US, fr-FR, it-IT, de-DE, es-ES,
bg-BG, cs-CZ, da-DK, nl-NL, fi-FI,
el-GR, hu-HU, id-ID, ja-JP, ko-KR,
nb-NO, pl-PL, pt-BR, pt-PT, ro-RO,
ru-RU, zh-CN, es-419, sv-SE, th-TH,
zh-TW, tr-TR, uk-UA, vi-VN

Enter fullscreen mode Exit fullscreen mode

The most commonly used are en-US (English), zh-CN (Simplified Chinese), zh-TW (Traditional Chinese), ja-JP (Japanese), and ko-KR (Korean). After all, these languages cover major markets—once you get these done, the others aren't so scary.

The main fields that need to be maintained include two:

  • about: Detailed description, supports rich text format
  • short_description: Short description, with a 300-character limit

Scope Concept

Steam app content can be divided into two scopes:

  • Base App: Main application content
  • DLC: Downloadable content, each DLC has independent content management

This distinction is important because DLCs typically need independent store descriptions, and a game may have multiple DLCs that need unified management. It's like life—some things are primary, some are additional, but they all need to be managed properly, or things become a mess.

Data Model Design

The system defines a clear data model to support multilingual content management:

// 28 supported language codes
const STEAMWORKS_SUPPORTED_LOCALES = [
  'en-US', 'fr-FR', 'it-IT', 'de-DE', 'es-ES',
  'bg-BG', 'cs-CZ', 'da-DK', 'nl-NL', 'fi-FI',
  'el-GR', 'hu-HU', 'id-ID', 'ja-JP', 'ko-KR',
  'nb-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO',
  'ru-RU', 'zh-CN', 'es-419', 'sv-SE', 'th-TH',
  'zh-TW', 'tr-TR', 'uk-UA', 'vi-VN'
];

// Supported fields
const STEAMWORKS_SUPPORTED_FIELDS = [
  'about',           // Detailed description
  'short_description' // Short description
];

// Content scope
type SteamworksScopeKind = 'base' | 'dlc';

Enter fullscreen mode Exit fullscreen mode

There are a few considerations in this model design—well, actually, it's just about making things a bit simpler:

  1. Use standard language code formats (like zh-CN instead of chinese)—after all, standard things are always more reliable
  2. Explicitly list field types for future extension—who knows if more fields will be needed later
  3. Distinguish scope types to support unified management of Base App and DLC—it's always good to keep things clear

File Storage Structure

Content is stored in .hagiclaw-data/steamworks-metadata/ in the project directory, using a hierarchical directory structure:

.hagiclaw-data/
└── steamworks-metadata/
    └── default-app/
        ├── workspace.json              # Workspace configuration manifest
        ├── base/                       # Base application content
        │   ├── en-US/
        │   │   ├── about.md
        │   │   └── short_description.md
        │   ├── zh-CN/
        │   │   ├── about.md
        │   │   └── short_description.md
        │   └── ...
        └── dlc/                        # DLC content
            └── turbo-engine/
                ├── en-US/
                │   ├── about.md
                │   └── short_description.md
                └── ...

Enter fullscreen mode Exit fullscreen mode

This structure design has several advantages—or at least, it's much better than the previous approach:

  1. Human-readable: Each content is an independent Markdown file that can be edited directly—after all, human eyes prefer to see things clearly
  2. Version control friendly: Text files make it easy to track change history and compare differences—so what was changed is clear at a glance
  3. Strong extensibility: Adding new languages or fields only requires creating new files—like building blocks, add whatever you want
  4. Clear structure: The directory structure intuitively reflects how content is organized—won't make people feel confused

workspace.json stores workspace configuration, including DLC list and language configuration information. After all, some things still need a manifest—otherwise, after a while, who remembers what they put where.

Markdown to BBCode Conversion

Steam uses BBCode format for rich text, not standard Markdown. This brings additional workload to content creation—either write BBCode directly or manually convert it later.

HagiCode's solution is: let developers create content in familiar Markdown, and the system automatically converts it to Steam BBCode. After all, people are always accustomed to what they're familiar with—why force yourself to adapt to those strange curly braces?

Conversion Rules

// Heading conversion
# HagiCode         [h1]HagiCode[/h1]
## Features         [h2]Features[/h2]

// Text styles
**bold text**      [b]bold text[/b]
*italic text*      [i]italic text[/i]
`code`             [code]code[/code]

// Links and images
[text](url)        [url=url]text[/url]
![alt](src)        [img src="{STEAM_APP_IMAGE}/extras/..."][/img]

// Lists
- item 1
- item 2           [*]item 1
                   [*]item 2
                   (wrapped in [list])

Enter fullscreen mode Exit fullscreen mode

Language Wrapping

When exporting, content needs to be wrapped with language tags:

wrapWithSteamLanguage(locale: SteamworksLocaleCode, bbcode: string): string {
  // Returns [lang=english]...[/lang] format
}

Enter fullscreen mode Exit fullscreen mode

Language codes need to be mapped to Steam's format:

  • en-USenglish
  • zh-CNschinese
  • zh-TWtchinese
  • ja-JPjapanese
  • ko-KRkorean

This mapping relationship isn't actually that complicated, it just needs to be remembered. After all, every platform has its own rules, we can only adapt.

Export Format

The exported JSON needs to meet Steamworks' structure requirements:

{
  "itemid": "1158573",
  "languages": {
    "english": {
      "app[content][about]": "[h1]HagiCode[/h1]\n[b]About[/b]...",
      "app[content][short_description]": "AI coding tool..."
    },
    "schinese": {
      "app[content][about]": "[h1]HagiCode[/h1]\n[b]关于[/b]...",
      "app[content][short_description]": "AI 编码工具..."
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

The key points aren't many, just need to remember these format requirements:

  1. itemid corresponds to Steam AppID
  2. Steam's language codes (like schinese) are used under languages
  3. Field paths use app[content][fieldName] format
  4. Values are converted BBCode strings

These rules seem a bit tedious, but you get used to them. After all, every platform has its own temperament, we can only adapt.

API Service Design

The system provides a complete REST API to support the multilingual content management workflow:

Load Workspace

GET /api/steamworks/metadata

Enter fullscreen mode Exit fullscreen mode

Returns workspace configuration, all languages, and field content. After all, there needs to be a place to pull everything out for viewing.

Save Content

POST /api/steamworks/metadata

{
  "scopeId": "base-app",
  "scopeKind": "base",
  "values": {
    "en-US": {
      "about": "Markdown content...",
      "short_description": "Short text..."
    },
    "zh-CN": {
      "about": "Markdown 内容...",
      "short_description": "简短文本..."
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

When saving, the system writes Markdown content to corresponding .md files. This way nothing gets lost—after all, memory is always unreliable.

Render Preview

POST /api/steamworks/metadata/preview

{
  "locale": "zh-CN",
  "field": "about",
  "content": "# HagiCode\n\n这是关于..."
}

Enter fullscreen mode Exit fullscreen mode

Returns Markdown rendering result and BBCode conversion result for easy previewing. Preview is like looking in a mirror—you should at least see what you look like before going out.

Export JSON

POST /api/steamworks/metadata/export

{
  "scopeId": "base-app",
  "scopeKind": "base"
}

Enter fullscreen mode Exit fullscreen mode

Generates Steamworks-format JSON that can be directly imported into the Steamworks backend. This step is essentially packaging everything up, ready for shipping.

DLC Management

POST /api/steamworks/metadata/dlc    // Create
PUT /api/steamworks/metadata/dlc     // Update
DELETE /api/steamworks/metadata/dlc  // Delete

Enter fullscreen mode Exit fullscreen mode

DLC management includes creating, updating, and deleting DLC metadata configurations. After all, DLC is also content and needs to be managed properly.

Usage Workflow

1. Access Metadata Panel

Open the Steamworks Metadata panel in the HagicLaw workspace, and the system will load the current workspace's configuration and content. Once all preparations are done, you can begin.

2. Select Edit Scope

Select Base App or a specific DLC in the left navigation. Each scope independently manages its multilingual content. Like organizing a room—first categorize things, then clean them up one by one.

3. Multilingual Matrix Editing

Expand the languages you need to edit, and directly edit the Markdown content for about and short_description. The system supports:

  • Real-time Markdown rendering preview
  • Steam BBCode conversion preview
  • Character count and length checking

These preview features are actually quite useful—at least you can know what your content looks like. After all, no one wants to write a bunch of stuff only to find the format is completely wrong.

4. Save Content

Click the save button, and content is automatically written to corresponding .md files. Files are included in Git version control for easy change tracking. Saving is like writing down memories—they won't be forgotten even after a long time.

5. Validation Checks

The system automatically checks:

  • Whether required fields are complete
  • Whether short_description exceeds 300 characters
  • Whether Markdown syntax is correct

These checks can avoid some basic errors—after all, humans make mistakes, it's always good to have a machine help watch over things.

6. Export JSON

Select the scope to export (Base App or specific DLC), and the system generates Steamworks JSON containing all languages. Copy the JSON and paste it into the Steamworks backend to complete the import. Once this step is done, the entire workflow is complete. Everything is ready, just waiting for release.

Notes

Language Code Mapping

The system's en-US corresponds to Steam's english, and zh-CN corresponds to schinese. This mapping is handled automatically during export, but needs attention when manually editing JSON. After all, some things machines can help you with, but some you still need to remember yourself.

BBCode Limitations

Steam only supports a subset of BBCode, and complex Markdown may not convert perfectly. It's recommended to check conversion results in preview. Preview is like looking in a mirror—check what you look like before going out.

Image Paths

Images are converted to [img src="{STEAM_APP_IMAGE}/extras/..."] placeholder format. Actual images need to be uploaded separately to the Steam backend. Images are sometimes more persuasive than text, just a bit more troublesome to upload.

Field Validation

short_description has a strict 300-character limit. The system validates before export, but it's recommended to control length during editing. After all, writing too many characters is useless—the platform only looks at the first 300, so you have to be concise.

Version Control

All Markdown files can be included in Git version control for easy change history tracking and collaborative editing. It's recommended to commit changes regularly. Version control is like a time machine that lets you return to a past moment and see what you wrote then.

DLC Management

DLC's itemId needs to correspond to the DLC AppID in the Steamworks backend. When creating a DLC, ensure the ID is accurate. IDs are hard to change once wrong, so it's better to be careful.

Summary

The core challenge of Steamworks multilingual metadata management lies in how to efficiently maintain large amounts of multilingual content. Through structured data models, human-friendly file storage, and automated conversion/export workflows, we can transform this tedious process into a manageable content creation workflow.

This solution has proven effective in the practice of the HagiCode project. We transformed from a manual, error-prone state to a structured, verifiable, collaborative workflow. This not only improved efficiency but also reduced human error. After all, when the tool is well-made, things become simple.

If you're developing applications for the Steam platform and need to maintain multilingual content, I hope this solution can provide some inspiration. Multilingual content management doesn't have to be a painful thing—with the right tools and workflows, it can become relatively easy. Or at least, not so despair-inducing...

References

If this article helped you:

Original Article & License

Thanks for reading. If this article helped, consider liking, bookmarking, or sharing it.
This article was created with AI assistance and reviewed by the author before publication.