Skip to content

Localization Guide

structured-changelog supports localized output in 6 languages. This guide explains how to use built-in translations and create custom overrides.

Built-in Languages

Code Language Example
en English (default) "Changelog", "Added", "Breaking"
de German "Änderungsprotokoll", "Hinzugefügt", "Breaking Changes"
es Spanish "Registro de cambios", "Añadido", "Cambios importantes"
fr French "Journal des modifications", "Ajouté", "Changements majeurs"
ja Japanese "変更履歴", "追加", "破壊的変更"
zh Chinese "变更日志", "新增", "破坏性变更"

CLI Usage

# Generate in French
schangelog generate CHANGELOG.json --locale=fr -o CHANGELOG.md

# Generate in Japanese
schangelog generate CHANGELOG.json --locale=ja -o CHANGELOG.md

# Use custom overrides
schangelog generate CHANGELOG.json --locale=fr --locale-file=./my-fr.json -o CHANGELOG.md

Library Usage

import "github.com/grokify/structured-changelog/renderer"

// Use built-in French translations
opts := renderer.DefaultOptions().WithLocale("fr")
md, err := renderer.RenderMarkdown(changelog, opts)

// Use custom overrides
opts := renderer.DefaultOptions().
    WithLocale("fr").
    WithLocaleOverrides("./my-fr.json")

Customizable Message IDs

Override any of these message IDs in your custom locale file:

Document Structure

ID English Default Description
changelog.title "Changelog" Document title
changelog.intro "All notable changes..." Intro paragraph
section.unreleased "Unreleased" Unreleased section header
section.yanked "YANKED" Yanked version marker

Header Text

The introductory header paragraph references standards and tools. Each part links to the appropriate localized documentation where available.

ID English Default Description
header.format_kacl "The format is based on [Keep a Changelog](url)" Keep a Changelog reference
header.versioning_semver "this project adheres to [Semantic Versioning](url)" SemVer reference
header.versioning_calver "this project uses [Calendar Versioning](url)" CalVer reference
header.commits_conventional "commits follow [Conventional Commits](url)" Conventional Commits reference
header.generated_by "this changelog is generated by [Structured Changelog](url)" Generator attribution
header.conjunction "and" Conjunction joining header clauses

Markers

ID English Default Description
marker.breaking "BREAKING:" Breaking change prefix
marker.maintenance "Maintenance" Maintenance release label
marker.versions_range "Versions {{.From}} - {{.To}}" Grouped versions header

Category Headers

ID English Default
category.highlights "Highlights"
category.breaking "Breaking"
category.upgrade_guide "Upgrade Guide"
category.security "Security"
category.added "Added"
category.changed "Changed"
category.deprecated "Deprecated"
category.removed "Removed"
category.fixed "Fixed"
category.performance "Performance"
category.dependencies "Dependencies"
category.documentation "Documentation"
category.build "Build"
category.tests "Tests"
category.infrastructure "Infrastructure"
category.observability "Observability"
category.compliance "Compliance"
category.internal "Internal"
category.known_issues "Known Issues"
category.contributors "Contributors"

Plural Forms (for compact maintenance summaries)

ID English Default
plural.dependency_updates {"one": "{{.Count}} dependency update", "other": "{{.Count}} dependency updates"}
plural.documentation_changes {"one": "{{.Count}} documentation change", "other": "{{.Count}} documentation changes"}
plural.build_changes {"one": "{{.Count}} build change", "other": "{{.Count}} build changes"}
plural.test_changes {"one": "{{.Count}} test change", "other": "{{.Count}} test changes"}
plural.other_changes {"one": "{{.Count}} other change", "other": "{{.Count}} other changes"}
plural.releases {"one": "{{.Count}} release", "other": "{{.Count}} releases"}

Custom Override File Format

Create a JSON file with only the messages you want to override:

{
  "messages": [
    {"id": "changelog.title", "translation": "Release Notes"},
    {"id": "category.added", "translation": "New Features"},
    {"id": "category.fixed", "translation": "Bug Fixes"},
    {"id": "marker.breaking", "translation": "⚠️ BREAKING:"}
  ]
}

Messages not included in your override file will use the built-in translations for the selected locale.

Examples

See examples/l10n/ for complete rendered examples in all 6 languages:

What Gets Localized

Localized (system labels):

  • Document title and introduction
  • Header text (Keep a Changelog, versioning, and generator references)
  • Section headers ("Changelog", "Unreleased", "Added", etc.)
  • Breaking change markers
  • Maintenance release summaries

Not localized (user content):

  • Entry descriptions (your changelog text)
  • Version numbers
  • Dates (always ISO 8601: YYYY-MM-DD)
  • Project names
  • Issue/PR references

This preserves the JSON IR as the canonical, language-agnostic source of truth.