Skip to main content
i18n Doctor automatically detects and parses the most common translation file formats. This guide explains how each format is processed and what structures are supported.

Supported Formats

JSON

.json files with flat or nested structures

YAML

.yaml and .yml files with nesting support

Gettext

.po files with msgid/msgstr entries

JSON Format

Flat Structure

The simplest format - direct key-value pairs:
en.json
{
  "welcome": "Welcome to our app",
  "login": "Log in",
  "signup": "Sign up",
  "logout": "Log out"
}

Nested Structure

i18n Doctor automatically flattens nested objects using dot notation:
{
  "auth": {
    "login": {
      "title": "Log In",
      "email": "Email address",
      "password": "Password",
      "button": "Sign in"
    },
    "signup": {
      "title": "Create Account",
      "button": "Sign up"
    }
  },
  "dashboard": {
    "welcome": "Welcome back",
    "stats": {
      "users": "Total Users",
      "revenue": "Revenue"
    }
  }
}
Nested structures are flattened only for analysis. Your original file structure remains unchanged.

Arrays in JSON

Arrays are flattened using numeric indices:
{
  "days": ["Monday", "Tuesday", "Wednesday"],
  "errors": {
    "validation": [
      "Field is required",
      "Invalid email format"
    ]
  }
}

Primitive Values

JSON supports strings, numbers, and booleans:
config.json
{
  "app_name": "i18n Doctor",
  "version": 1.0,
  "is_active": true,
  "max_users": 1000
}
All values are converted to strings internally:
Flattened
{
  "app_name": "i18n Doctor",
  "version": "1.0",
  "is_active": "true",
  "max_users": "1000"
}
Primitive values (numbers, booleans) are converted to strings during parsing for consistent comparison across locales.

YAML Format

Basic YAML

YAML files use indentation to define structure:
en.yml
welcome: Welcome to our app
login: Log in
signup: Sign up
logout: Log out

Nested YAML

Supports parent-child relationships:
auth:
  login:
    title: Log In
    email: Email address
    password: Password
    button: Sign in
  signup:
    title: Create Account
    button: Sign up

dashboard:
  welcome: Welcome back
  stats:
    users: Total Users
    revenue: Revenue

YAML Comments

Comments are ignored during parsing:
en.yml
# Authentication strings
auth:
  login: Log in  # Main login button
  signup: Sign up

# Dashboard content
dashboard:
  welcome: Welcome back
YAML comments are preserved in your original files but don’t affect the i18n analysis.

Quoted Strings

Both single and double quotes are supported:
en.yml
message1: 'Single quoted string'
message2: "Double quoted string"
message3: Unquoted string
special: "String with: colons"

Gettext (.po) Format

Gettext is the standard for internationalization in many frameworks (Django, WordPress, etc.).

Basic .po Structure

messages.po
# Comment
msgid "welcome"
msgstr "Welcome to our app"

msgid "login"
msgstr "Log in"

msgid "signup"
msgstr "Sign up"

Multi-line Strings

Gettext supports string continuation:
messages.po
msgid "long_message"
msgstr "This is a very long message that "
"spans multiple lines for better "
"readability in the source file."

msgid "paragraph"
msgstr ""
"First paragraph.\n"
"\n"
"Second paragraph."
msgid "terms"
msgstr "By signing up, you agree to our "
"Terms of Service and Privacy Policy."

Empty Translations

Empty msgstr values are treated as untranslated:
fr.po
msgid "welcome"
msgstr "Bienvenue"

msgid "login"
msgstr ""  # Untranslated - will show in report

msgid "signup"
msgstr "S'inscrire"
In .po files, an empty msgstr means “untranslated.” This will be flagged in your report as needing attention.

Metadata Comments

Gettext comments and metadata are ignored:
messages.po
# TRANSLATOR: Context for the translator
#: src/auth.js:12
#, fuzzy
msgid "login"
msgstr "Log in"
Only msgid and msgstr are extracted for analysis.

Format Detection

i18n Doctor automatically detects format based on file extension:
ExtensionFormatParser
.jsonJSONJSON.parse() with flattening
.yaml, .ymlYAMLLightweight YAML parser
.poGettextmsgid/msgstr extractor
Format detection is automatic. Just ensure your files use standard extensions.

Common Patterns

React i18next

Typically uses nested JSON:
public/locales/en/translation.json
{
  "common": {
    "buttons": {
      "submit": "Submit",
      "cancel": "Cancel"
    }
  },
  "pages": {
    "home": {
      "title": "Welcome",
      "subtitle": "Get started today"
    }
  }
}

Vue i18n

Supports both JSON and YAML:
{
  "message": {
    "hello": "Hello, {name}!"
  }
}

Next.js with next-intl

Nested JSON in messages/ directory:
messages/en.json
{
  "Index": {
    "title": "Hello world!"
  },
  "About": {
    "title": "About us"
  }
}

Django gettext

Standard .po files:
locale/fr/LC_MESSAGES/django.po
msgid "Welcome"
msgstr "Bienvenue"

msgid "Login"
msgstr "Connexion"

Limitations

While i18n Doctor supports unlimited nesting depth, extremely deep structures (10+ levels) may create very long flattened keys. Consider refactoring for better organization.
The YAML parser is lightweight and supports common patterns. Advanced YAML features (anchors, tags, multi-doc files) are not supported. Use standard key-value structures.
Each .po file is processed independently. If your project uses domain-specific .po files (e.g., django.po, messages.po), each will be analyzed separately.
Compiled formats like .mo (compiled gettext) are not supported. Use source .po files instead.

File Detection

i18n Doctor scans your repository for locale files in common locations:
  • locales/
  • i18n/
  • public/locales/
  • messages/
  • locale/
  • translations/
  • lang/
Files matching these patterns are automatically included:
  • **/*.json
  • **/*.yaml, **/*.yml
  • **/*.po
Organize your locale files in standard directories (locales/, i18n/) for automatic detection.

Next Steps

Understanding Reports

Learn how to interpret your scan results

Lingo.dev Integration

Fix missing translations with AI-powered translation

Build docs developers (and LLMs) love