Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvement: Context #1281

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/ref/catalog-formats.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The advantages of this format are:

#: src/App.js:3
# Comment for translators
msgctx "context"
msgid "messageId"
msgstr "Translated Message"

Expand Down Expand Up @@ -79,9 +80,9 @@ With `po-gettext`, plural messages are exported in the following way, depending
Note that this format comes with several caveats and should therefore only be used if using ICU plurals in PO files is
not an option:

- Nested/multiple plurals in one message as shown in :jsmacro:`plural` are not supported as they cannot be expressed
- Nested/multiple plurals in one message as shown in :jsmacro:`plural` are not supported as they cannot be expressed
with gettext plurals. Messages containing nested/multiple formats will not be output correctly.

- :jsmacro:`select` and :jsmacro:`selectOrdinal` cannot be expressed with gettext plurals, but the original ICU format
is still saved to the `msgid`/`msgstr` properties. To disable the warning that this might not be the expected
behavior, include :code:`{ disableSelectWarning: true }` in the :conf:`formatOptions`.
Expand Down Expand Up @@ -123,6 +124,7 @@ process catalog data.
"messageId": {
"translation": "Translated message",
"defaults": "Default message",
"context": "more context",
"description": "Comment for translators",
"origin": [["src/App.js", 3]]
},
Expand Down
77 changes: 70 additions & 7 deletions docs/ref/macro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,12 @@ into a *Message Descriptor* wrapped inside of ``i18n._`` call.
message?: String,
values?: Object,
formats?: Object,
comment?: string
comment?: string,
context?: string
}

``id`` is message ID and the only required parameter. ``id`` and ``message``
are extracted to message catalog. Only ``id``, ``values``, and ``formats``
``id`` is message ID and the only required parameter. ``id``, ``message``, ``comment``
and ``context`` are extracted to message catalog. Only ``id``, ``context``, ``values``, and ``formats``
are used at runtime, all other attributes are removed from production code
for size optimization.

Expand Down Expand Up @@ -340,6 +341,40 @@ as if it were wrapped in ``t`` macro. ``message`` also accepts any other macros:
values: { value }
})

You can also use ``context`` to have different entries in catalog for
identical messages and allow translator to provide differents translations:

.. code-block:: jsx

import { t } from "@lingui/macro"
const message = t({
comment: 'Commercial term for Free offer',
context: 'commercial subapp',
message: 'Free'
})

const anotherMessage = t({
comment: 'Like in "free to move the item"',
context: 'main subapp',
message: 'Free'
})

// ↓ ↓ ↓ ↓ ↓ ↓

import { i18n } from "@lingui/core"
const message = i18n._(/*i18n*/{
comment: 'Commercial term for Free offer',
context: 'commercial subapp',
message: 'Free'
})

const anotherMessage = i18n._(/*i18n*/{
comment: 'Like in "free to move the item"',
context: 'main subapp',
message: 'Free'
})


plural
^^^^^^

Expand Down Expand Up @@ -437,8 +472,21 @@ two counters:

.. important::

Use ``plural`` inside :jsmacro:`t` macro if you want to add custom ``id``
or ``comment`` for translators.
Use ``plural`` inside :jsmacro:`t` macro if you want to add custom ``id``, ``comment``
or ``context`` for translators.

.. code-block:: jsx

import { t } from "@lingui/macro"
const message = t({
comment: 'Purchase summary',
context: 'cart',
message: plural(count, {
one: "# article",
other: "# articles"
})
})


selectOrdinal
^^^^^^^^^^^^^
Expand Down Expand Up @@ -527,6 +575,7 @@ Unlike the other JS macros, it doesn't wrap generated *MessageDescription* into
type MessageDescriptor = {
id?: string,
message?: string,
context?: string,
comment?: string
}

Expand Down Expand Up @@ -576,7 +625,7 @@ string literals don't need to be tagged with :jsmacro:`t`.
}

``comment`` is a comment for translators. It's extracted to the message catalog
and it gives extra context for translators. It's removed from production code:
and it gives extra context for translators. It is removed from production code:

.. code-block:: jsx

Expand Down Expand Up @@ -611,7 +660,12 @@ and it gives extra context for translators. It's removed from production code:

const message = "Navigation / About"

``message`` and ``comment`` are used in message catalogs only.
``message``, ``comment`` and are used in message catalogs only.

``context`` is for both translators and developers. Unlike a comment, it creates
a new entry in the catalog and allows to distinguish equal messages that would
need different translation or to create subset of messages.
It is also used in production code at runtime.

JSX Macros
----------
Expand Down Expand Up @@ -644,6 +698,14 @@ comment
Comment for translators to give them additional context about the message.
It's removed from production code.

context
~~~~~~~~~~~

Context is for both translators and developers. Unlike a comment, it creates
a new entry in the catalog and allows to distinguish equal messages that would
need different translation or to create subset of messages.
It is also used in production code at runtime.

render
~~~~~~

Expand All @@ -658,6 +720,7 @@ Trans

:prop string id: Custom message ID
:prop string comment: Comment for translators
:prop string context: Context to group messages or distinguish similar messages

:jsxmacro:`Trans` is the basic macro for static messages, messages with variables,
but also for messages with inline markup:
Expand Down
10 changes: 5 additions & 5 deletions examples/create-react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@lingui/react": "^3.13.2",
"@lingui/core": "^3.13.2",
"@lingui/react": "^3.14.1",
"@lingui/core": "^3.14.1",
"react": "^17.0.1",
"react-dom": "^17.0.1"
},
Expand Down Expand Up @@ -42,8 +42,8 @@
"@types/react-dom": "^16.9.9",
"react-scripts": "4.0.0",
"typescript": "^4.0.5",
"@lingui/cli": "^3.13.2",
"@lingui/loader": "^3.13.2",
"@lingui/macro": "^3.13.2"
"@lingui/cli": "^3.14.1",
"@lingui/loader": "^3.14.1",
"@lingui/macro": "^3.14.1"
}
}
5 changes: 4 additions & 1 deletion examples/create-react-app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import './App.css';
import React, { useState } from 'react';
import { Trans, Plural } from "@lingui/macro";
import { Trans, Plural, t } from "@lingui/macro";
import { i18n } from "@lingui/core";

import { locales, dynamicActivate } from './i18n';
Expand Down Expand Up @@ -46,6 +46,9 @@ function App() {
I have a balance of {i18n.number(1_000_000, { style: "currency", currency: "EUR" })}
</Trans>
</div>
<h3><Trans context="example ctxt">Context example:</Trans></h3>
<div>{t`Hello World`}</div>
<div>{t({context: 'example ctxt', message: 'Hello World'})}</div>
</header>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion examples/create-react-app/src/locales/cs/messages.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions examples/create-react-app/src/locales/cs/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ msgstr "Příklad formátovače data:"
msgid "Decrement"
msgstr "Úbytek"

#: src/App.tsx:51
msgid "Hello World"
msgstr "Ahoj Brno"

#: src/App.tsx:45
msgid "I have a balance of {0}"
msgstr "Mám zůstatek {0}"
Expand All @@ -43,6 +47,16 @@ msgstr "Příklad množného čísla:"
msgid "Today is {0}"
msgstr "Dnes je {0}"

#: src/App.tsx:49
msgctxt "example ctxt"
msgid "Context example:"
msgstr "Kontext příklad:"

#: src/App.tsx:52
msgctxt "example ctxt"
msgid "Hello World"
msgstr "Ahoj Kontext"

#: src/App.tsx:31
msgid "{count, plural, zero {There are no books} one {There's one book} other {There are # books}}"
msgstr "{count, plural, zero {Nejsou žádné knihy} one {Je tu jedna kniha} other {Existuje # knih}}"
2 changes: 1 addition & 1 deletion examples/create-react-app/src/locales/en/messages.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions examples/create-react-app/src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ msgstr "Date formatter example:"
msgid "Decrement"
msgstr "Decrement"

#: src/App.tsx:51
msgid "Hello World"
msgstr "Hello World"

#: src/App.tsx:45
msgid "I have a balance of {0}"
msgstr "I have a balance of {0}"
Expand All @@ -45,6 +49,16 @@ msgstr "Plurals example:"
msgid "Today is {0}"
msgstr "Today is {0}"

#: src/App.tsx:49
msgctxt "example ctxt"
msgid "Context example:"
msgstr "Context example:"

#: src/App.tsx:52
msgctxt "example ctxt"
msgid "Hello World"
msgstr "Hello Context"

#: src/App.tsx:31
msgid "{count, plural, zero {There are no books} one {There's one book} other {There are # books}}"
msgstr "{count, plural, zero {There are no books} one {There's one book} other {There are # books}}"
2 changes: 1 addition & 1 deletion packages/babel-plugin-extract-messages/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function addMessage(
if (messages.has(context)) {
const existingContext = messages.get(context)
if (existingContext.has(id)) {
const message = messages.get(id)
const message = existingContext.get(id)
// only set/check default language when it's defined.
if (message.message && newDefault && message.message !== newDefault) {
throw path.buildCodeFrameError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ Object {
js-with-macros.js,
39,
],
Array [
js-with-macros.js,
44,
],
],
},
},
Expand All @@ -62,7 +66,7 @@ Object {
origin: Array [
Array [
js-with-macros.js,
44,
49,
],
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const tWithContextB = t({
context: "Context1"
})

const tWithContextSameAsB = t({
id: "Some other ID",
context: "Context1"
})

const defineMessageWithContext = defineMessage({
id: "Some ID",
context: "Context2"
Expand Down
Loading