Skip to content

feat: store msgctxt from Gettext (.po) files#3459

Draft
Anty0 wants to merge 1 commit intomainfrom
jirikuchynka/po-msgctxt
Draft

feat: store msgctxt from Gettext (.po) files#3459
Anty0 wants to merge 1 commit intomainfrom
jirikuchynka/po-msgctxt

Conversation

@Anty0
Copy link
Collaborator

@Anty0 Anty0 commented Feb 6, 2026

Summary

  • Parse and store msgctxt from PO files instead of ignoring it with a warning
  • Combine msgctxt + \u0004 (EOT) separator + msgid as the key name, following the GNU gettext standard
  • Store raw msgctxt in key custom metadata (_poFileMsgCtxt)
  • Export msgctxt line before msgid when the custom value is present
  • Display msgctxt visually in the translations UI with a dimmed prefix and | separator

Closes #3053

Summary by CodeRabbit

New Features

  • Added full support for PO file message contexts (msgctxt). Translations with context information can now be properly imported, stored, and exported while maintaining all context metadata
  • Translation keys with message context are now visually distinguished in the interface, making it easier to identify and manage contextual translations

Import msgctxt as part of the key name using the GNU gettext standard
EOT separator (\u0004), store the raw value in custom key metadata for
reliable round-trip export. Display context visually in the translations
UI with a pipe separator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 6, 2026

📝 Walkthrough

Walkthrough

This PR implements support for storing and handling the msgctxt (message context) field from Gettext (.po) files. Changes span the entire PO format lifecycle: parser now captures msgctxt instead of treating it as unsupported, the processor combines it with msgid as the key and stores context as metadata, the exporter reconstructs msgctxt on output, and the frontend displays context distinctly.

Changes

Cohort / File(s) Summary
PO Format Constants
backend/data/src/main/kotlin/io/tolgee/formats/po/contsants.kt
Added two constants: PO_FILE_MSG_CTXT_CUSTOM_KEY to identify msgctxt metadata and PO_MSGCTXT_SEPARATOR (Unicode U+0004) to delimit msgctxt from msgid in combined keys.
PO Parsing
backend/data/src/main/kotlin/io/tolgee/formats/po/in/PoParser.kt
Replaced error emission for msgctxt with flag-based handling; now collects msgctxt content via expectMsgCtxt state flag instead of rejecting it as unsupported.
Translation Data Model
backend/data/src/main/kotlin/io/tolgee/formats/po/in/data/PoParsedTranslation.kt
Added msgctxt StringBuilder property to store message context during parsing.
PO Processing
backend/data/src/main/kotlin/io/tolgee/formats/po/in/PoFileProcessor.kt
Introduced buildKeyName() helper to combine msgctxt and msgid with separator, and storeMsgCtxt() to persist context as custom metadata; applied to both singular and plural translation paths.
PO Exporting
backend/data/src/main/kotlin/io/tolgee/formats/po/out/PoFileExporter.kt
Added logic to extract msgctxt from combined key, write msgctxt field to file, and use actual msgid (with separator stripped) for msgid and plural forms; introduced writeMsgCtxt() helper and updated writeMsgIdPlural() signature.
Frontend Display
webapp/src/views/projects/translations/CellKey.tsx
Replaced direct keyName rendering with KeyNameWithContext component that splits on separator and displays msgctxt and msgid as separate styled elements.
Parser Tests
backend/data/src/test/kotlin/io/tolgee/unit/formats/po/in/PoParserTest.kt
Added test verifying correct parsing of msgctxt, msgid, msgstr, and plural forms across contextual and non-contextual entries.
Processor Tests
backend/data/src/test/kotlin/io/tolgee/unit/formats/po/in/PoFileProcessorTest.kt
Added tests validating msgctxt handling: distinct key generation per context, correct metadata storage, and preservation of non-contexted keys.
Exporter Tests
backend/data/src/test/kotlin/io/tolgee/unit/formats/po/out/PoFileExporterTest.kt
Added tests for msgctxt export with simple and plural forms, using helper exporters and constants to validate output structure.
Test Resource
backend/data/src/test/resources/import/po/example_msgctxt.po
Added German PO translation file with msgctxt examples: menu (Open/Close), dialog (Open), stats (plural), and uncontexted Hello entry.

Sequence Diagram(s)

sequenceDiagram
    participant PO as PO File
    participant Parser as PoParser
    participant Model as PoParsedTranslation
    participant Processor as PoFileProcessor
    participant Storage as Translation<br/>Storage
    
    PO->>Parser: Read msgctxt field
    Parser->>Parser: Set expectMsgCtxt flag
    Parser->>Model: Append to msgctxt StringBuilder
    PO->>Parser: Read msgid field
    Parser->>Model: Store msgid
    PO->>Parser: Read msgstr field
    Parser->>Model: Store msgstr
    Processor->>Model: Retrieve msgctxt & msgid
    Processor->>Processor: buildKeyName()<br/>Result: msgctxt\u0004msgid
    Processor->>Storage: Store key with<br/>msgctxt metadata
    Storage->>Storage: msgctxt field =<br/>PO_FILE_MSG_CTXT_CUSTOM_KEY
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • JanCizmar

🐰 Hopping through gettext fields so spry,
msgctxt now captured, no more goodbye,
Context and messages in harmony blend,
With separator magic, confusion will end! ✨🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: store msgctxt from Gettext (.po) files' accurately describes the main change: adding support for parsing and storing msgctxt from PO files.
Linked Issues check ✅ Passed All coding objectives from issue #3053 are met: msgctxt is imported using key scheme, custom metadata stores raw msgctxt for round-trip export, UI displays msgctxt with context separator, and comprehensive tests validate the implementation.
Out of Scope Changes check ✅ Passed All changes are directly related to msgctxt support: parser/exporter modifications, constant definitions, test resources, and minimal UI display logic for the context separator.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jirikuchynka/po-msgctxt

Comment @coderabbitai help to get the list of available commands and usage tips.

@Anty0 Anty0 marked this pull request as draft February 6, 2026 10:56
@JanCizmar
Copy link
Contributor

Q: Why do you store it also in the meta field?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Store msgctxt from Gettext (.po) files

2 participants