Hey everyone! 👋
I've been deep in the weeds lately trying to standardize how my team handles multi-language content for our documentation and marketing sites, and I wanted to share what I've learned—and hopefully get your insights too. We use a mix of static site generators and headless CMS setups, and the translation layer was always a bit of an afterthought until it became a scaling nightmare.
From my experience, the "best" way really depends on your stack and workflow, but I'm a firm believer in treating translations as a first-class citizen in your CI/CD pipeline. You can't just bolt it on at the end.
Here’s the approach that’s been working for us, broken down:
**1. Separate Content from Structure**
Keep your translatable strings in a format that's agnostic to your presentation layer. We use `JSON` or `YAML` files structured by locale.
```json
// locales/en.json
{
"welcome": {
"heading": "Welcome to StackInsight",
"subtitle": "Join the community"
}
}
// locales/es.json
{
"welcome": {
"heading": "Bienvenido a StackInsight",
"subtitle": "Únete a la comunidad"
}
}
```
**2. Automate the Translation Sync**
Manual copy-pasting is a trap. We use a CLI tool (`i18next-parser` for our JS projects, `ttxt` for others) to extract new keys from source code into our base language file. Then, we push *only* the new or modified keys to a translation service (like Crowdin or Lokalise) via their API. The updated translations are pulled back as part of our nightly build.
**3. Integrate into the Build Process**
This is the GitOps/devops part I love. Our build script checks for missing translations. If a required locale is incomplete, the build *fails*, not just falls back. This forces us to keep everything in sync.
```bash
#!/bin/bash
# Example build check snippet
for locale in en es fr de;
do
if ! jq empty "./locales/${locale}.json"; then
echo "❌ Invalid JSON for ${locale}"
exit 1
fi
done
echo "✅ All locale files are valid."
```
**4. Handle Dynamic Content Differently**
For user-generated content or content from a CMS, we use a database with a `translations` table linked by a common key. The API then selects the correct language based on the `Accept-Language` header or a user preference.
The biggest pitfalls we've hit:
* **Context for translators:** A string like "Run" could be a verb or a noun. We now always add comments/context in our translation files.
* **Layout breaks:** Translated text can be much longer or shorter. Design with flexibility in mind—use CSS that accommodates text expansion.
* **Not translating URLs:** Remember to localize slugs if needed (`/en/blog/post` vs `/es/blog/articulo`), and consider hreflang tags for SEO.
I'm curious—how are you all managing this? Are you using any specific services, or have you built an in-house solution? Any horror stories or brilliant automations to share?
— francesc
— francesc