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

messages.json is looking different than in documentation #53

Closed
vitexikora opened this issue Aug 8, 2017 · 10 comments
Closed

messages.json is looking different than in documentation #53

vitexikora opened this issue Aug 8, 2017 · 10 comments

Comments

@vitexikora
Copy link

vitexikora commented Aug 8, 2017

Following https://lingui.gitbooks.io/js/tutorials/react.html got me to:

Now we're ready to extract messages:
$ lingui extract

And then it shows nicely formatted language file:

{
  "Message Inbox": "",
  "See all <0>unread messages</0> or <1>mark them</1> as read.": "",
  "{messagesCount, plural, one {There's {messagesCount} message in your inbox.} other {There're {messagesCount} messages in your inbox.}}": "",
  "Last login on {lastLogin, date}": ""
}

However mine looks very different, containing origin values (it does compile though):

{
  "StringOne": {
    "translation": "",
    "origin": [
      [
        "src\\components\\common\\Header.js",
        26
      ]
    ]
  },
  "StringTwo": {
    "translation": "",
    "origin": [
      [
        "src\\components\\common\\Header.js",
        53
      ]
    ]
  }
}

What am I doing wrong? I was just following the tutorial.

@tricoder42
Copy link
Contributor

That's definitely a bug. Tutorial is outdated, that format was using in 0.x version of jsLingui.

@vitexikora
Copy link
Author

Ah, so this is meant to be correct. It is however far less user-friendly for a translator - a lot of unneccessary cruft for somebody, who should just translate the strings. Could there be a switch (eg. lingui extract --compact)?

@tricoder42
Copy link
Contributor

There might be a switch --format=compact. I imagine somebody would like to export messages in nested JSON (e.g. invoices.Invoice.title message would be nested inside invoices, Invoice and title keys) or completely different format (like XML, XLIFF). This could be also configured globally in package.json.

I change the format, because I needed default message. When translator gets a message catalog with keys like invoices.Invoice.title they hardly know what the message should be. Having Invoice {numInvoice} in defaults helps a lot. Also, I wanted to add another metadata like origin on message and potentially format of message (ICU) so online or desktop editing software has more information about the message.

What do you think about the format configuration option? Would you mind working on PR for this feature?

@vitexikora
Copy link
Author

Your solution is even better, however I am currently too busy to improve your lib. I convinced my boss to use jsLingui on new projects instead of react-i18n we used on others, mainly because of lingui-cli, which seemed awesome, however there were several bugs that I reported and I spent with it a whole day getting it to work. This project seems very promising though, few more features in my head and it could be the ultimate translation tool...

@tricoder42
Copy link
Contributor

Sounds good.

Don't worry, I'm gonna spend some time on grooming jsLingui issues, so I'll probably sweep this one as well.

If you still had some spare time, I'm curious what were the biggest blockers/pain points when you were implementing this (except for the bugs you've already reported).

@vitexikora
Copy link
Author

The bad thing is, that when using a stable non-beta library (>= 1.0), I do not expect any bugs during simple stuff, so I always expected, that Im doing something wrong, so there was a LOT of debugging and breaking code into pieces... Except from what I have reported, I spent a lot of time trying to achieve having some translated texts in a separate config file, eg.
routeConfig.js

export default [
[route: '/', title: 'Homepage'],
[route: '/about', title: 'About'],
...etc
]

and then translate the title in components that import this config

const title = i18n.t([route.title])

I tried to bypass your variable-aware translation system by passing an array to the t function, instead of using it as tag, I even created a mock i18n object in the config file in order to get them into extracted translations, however after many tries it just didnt work, so I had to stick with having these lists directly in components...

I will post some feature requests regarding this. I believe it would be very beneficial to have an alternate way to translate texts, without the variable and node separation. Eg. <Trans raw>This will be translated literally even with this {var}</Trans> or i18n.translateRaw()

@tricoder42
Copy link
Contributor

Use i18n._("Raw string") for this, that's the "raw" method. In React, you have to use <Trans id="Raw string" />. I'll add this into docs.

However, this way the message won't be extracted. I need to add sth like i18n.noop which will just mark static messages for extraction, but won't perform any translation. So your example would be:

export default [
[route: '/', title:  i18n.noop('Homepage')],
[route: '/about', title: i18n.noop('About')],
...etc
]

And later you would use:

const title = i18n._(route.title)

// or
<Trans id={route.title} />

Good points anyway. Thank you and sorry for any inconveniences.

@vitexikora
Copy link
Author

Nice, I should have asked :)
I only have 2 suggestions:

  • With the Trans component - is it ok to use the ID for that? What if someone would like a raw string with an ID? Maybe it would be better to use a different prop..
  • For the i18n.noop I would still need the i18n object, is it neccessary for the extraction? Slightly better would be a single purpose helper, that wouldnt need explicit instantiation, like:
import helper from 'lingui-react/helper'

export default [
[route: '/', title:  helper.markForExtraction('Homepage')],
[route: '/about', title: helper.markForExtraction('About')],
...etc
]

@tricoder42
Copy link
Contributor

With the Trans component - is it ok to use the ID for that? What if someone would like a raw string with an ID? Maybe it would be better to use a different prop..

I don't understand what you mean. Either you use message IDs or source language as IDs:

export default [
[route: '/', title:  noop('Homepage')],
[route: '/about', title: noop('About')],
]

or

export default [
[route: '/', title:  noop('routes.Homepage.title')],
[route: '/about', title: noop('routes.About.title')],
]

In both cases i18n._(route.title) is equivalent to <Trans id={route.title} />

What might be missing in second example is default message, but we could use the same function signature as i18n.t: noop('translation.title', { defaults: 'Message with {variable}' }). However, later you would have to define values manually:

i18n.t('translation.title', { values: { variable: '42' } })

// or

<Trans id="translation.title" values={{ variable: '42' }} />

For the i18n.noop I would still need the i18n object, is it neccessary for the extraction? Slightly better would be a single purpose helper, that wouldnt need explicit instantiation, like:

You're absolutely right. Simple noop function is enough:

import { noop } from 'lingui-i18n'
// or
// import { noop } from 'lingui-react'
// this import and noop call will be removed after transformation anyway

export default [
[route: '/', title:  noop('Homepage')],
[route: '/about', title: noop('About')],
]

@tricoder42
Copy link
Contributor

Create a new issue for this feature: #60

@tricoder42 tricoder42 mentioned this issue Aug 27, 2017
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants