lingui / lingui/js-lingui

Better handling of "key" based messages in po files

Open
#2,391 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
5.9k
Forks
457
Avg merge
1d 23h
Merged PRs (30d)
16

Description

### Problem Description

Currently messages with explicitly defined id stored in PO files in very hacky way:

```po
#. js-lingui-explicit-id
msgctxt "my context"
msgid "custom.id"
msgstr ""

msgctxt "my context"
msgid "with generated id"
msgstr ""
```

The id is printed into the `msgid`, also we need to add a flag such `js-lingui-explicit-id` to tell formatter that on deserialize it should use this `msgid` as-is as id and not treat it as a source text.

The entry lacks the original message, and despite we can print this message into the translation as i did [here](https://github.com/lingui/js-lingui/pulls), it still not following the spec.

This brings a lot of hassle, because this is far from the original gettext spec and probably not working problem-free with any known TMS on the market.

### Proposed Solution

I dig into integration with translation.io [here](https://github.com/lingui/js-lingui/pull/2388) and took inspiration from how they approached it

Instead of writing `key` into the `msgid` we can write it into the context:

```po
msgctxt "custom.id"
msgid "Message with custom id"
msgstr ""
```

According to the gettext spec `msgid + msgctxt` creates a uniq pair, so adding `key` to context will do the trick, and will create a uniq entry only for that message.

This is fully following spec, no hacks, no tricks. All TMS should work with this approach.

## Opened questions?

### What should we do with the original context if provided?

By the spec, purpose of the context is to differentiate (creatte two separate entries) messages with the same source text. So it's exactly the same what `id` is doing. If the developer wants to leave a comment for the translator - better to use comment property.

So one solution is ignore originally passed context, and for example print a warning when both `id` and `context` provided.

Option number 2 - concatenate - (id + original context) - but honestly, i'm voting for more restricted approach and not giving a confusing options.

### How to identify during de-serialization that `context` is a custom key and not a real context?

I'm thinking of adding a special prefix to that context

```po
msgctxt "lingui-id:custom.id"
msgid "Message with custom id"
msgstr ""
```

So if the string started from the `lingui-id:` - it's a custom id, take it as-is. If it's not, use it as context for `generateMessageId(source, context)`

### How to migrate catalogs?

For a long time i advocated for not using `key-based` approach, but i admit that there still might be a group of developers using it.

We need a migrate comand, i know that `lingui-extract` already has some migrate functionality, but this is not enough. I'm thinkinh of creating an another command (or package) with it's own config just for migration.

The migration from code-perspective is straight forward, we need to load catalogs using old version with one parameters, and then save with a another one. I'm thinking of something like:

```ts
// migrator.config.js
import {defineConfig} from "@lingui/catalogs-migrator"
import {formatter as po} from "@lingui/format-po"

export default defineConfig({
from: po({...oldSettings}),
to: po({...newSettings}),
})
```

```sh
lingui-migrator --config migrator.config.js
```

### Alternatives Considered

Leave it as-is

### Additional Context

_No response_

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the existing PO formatter and the lingui-extract migration functionality mentioned in the issue, then compare the proposed context-prefix approach with current serialization and deserialization. Review the catalogs-migrator configuration and CLI examples, and consider the original-context and legacy-catalog cases. Done means key-based entries follow the gettext format and existing catalogs can be migrated.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
localization, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.