Closed kirillku closed 4 years ago
At least development={dev}
is required, because I18nProvider doesn't have bundled message parser.
In production parser isn't required, because messages in catalogs are parsed and compiled to pure functions. However, in development it's necessary to use development
prop and pass development data (plural rules and message parser).
Feel free to reopen if you have more questions.
I have added <I18nProvider development={dev} catalogs={{}} />
, but it still shows translations strings instead of default values in production (in dev it works fine). If there are any way to generate empty catalog, so it will include only those helper functions?
And as a possible feature, what do you think about making components work even without I18nProvider
or with empty I18nProvider
. Then components will still work with default values. It can be used when different projects share same common components and only one require translations (my case). Also, there will be no need to compile and include default language. For example, right now I'm just compiling english messages.json
where all values are empty strings, which looks strange.
In production you should use compiled message catalogs always. There're guards all over the code, which checks that NODE_ENV !== 'production'
and only then development code is executed. So it won't work even if you had some sort of empty catalog. It's similar to how prop-types work. In production, all unnecessary code is removed, minimizing the bundle size.
The easiest way is simply run lingui extract; lingui compile
and use compiled message catalog. I understand it looks weird if you have just one messages.json
, but it works in general case.
Btw, if you're using English in your source code (e.g. Inbox Title
instead of message IDs like Inbox.title
), you should set "sourceLocale": "en"
in your lingui config. That way you should never bother about filling translation in en/messages.json
.
About your feature request: Sounds interesting. It would be really great if we could use components even outside i18n context. It might be possible by compiling source code without lingui babel plugins. Then we could update Trans
component to work even without I18nProvider
. My only concern are all other components, like Plural
, Select
, DateFormat
, NumberFormat
, because these components actually need language data (plurals, formats, etc).
I have "sourceLocale": "en"
and "fallbackLocale": "en"
in my package.json
, but if I will remove en: unpackCatalog(en)
from I18nProvider
's catalogs, it will not work and also will show warning.
I think if it would be possible for components to work without I18nProvider
, all components could decide just by props, what to output, anyway it would be better than translation string. For example <Plural value={count} one="# book" other="# books" />
is already enough to show something readable. It will be really cool feature to have. As for me, it is the only missing part to make lingui the most userfriendly intl lib for react. I can also help if you will give me some kind of starting point.
Yes, in production you always need to load compiled message catalog. In development you either need source catalog and development data or compiled catalog as well.
Let's try to figure out how it should work.
Babel plugins transfrom all i18n components to Trans
and convert children to ICU MessageFormat string. For example:
<Trans>Hello <strong>{world}</strong></Trans>
becomes
<Trans id="Hello <0>{world}</0>" values={{ world }} components={[<strong />]} />
Trans
component renders Hello <0>{world}</0>
instead of original children. That's why we need to disable babel plugin, when we plan to use it without I18nProvider
.
The situation is similar to singular translations, but there's one more problem: I18nProvider provides also plural data, which is basically a function number -> string
which maps a number of items to plural rule (e.g: 1 -> one, 2 -> other, 3 -> other, for English).
To avoid loading plural rules for all languages, there should be some way to define what's the source language and then inject language data.
How it seems to me, if Plural
is used without I18nProvider
, then it should decide based on props, which text to show, it shouldn't be exact right form, just something acceptable. other
prop is required and other props will be used if specified. And if the user want to show exact right messages, then he needs to connect I18nProvider
with language catalog.
<Plural value={count} other="# books" />
0 books, 1 books, 2 books, 5 books
<Plural value={count} one="# book" other="# books" />
0 books, 1 book, 2 books, 5 books
<Plural value={count} zero="no books" one="# book" few="# bookz" other="# books" />
no books, 1 book, 2 bookz, 5 books
<I18nProvider language='en' catalogs={{ en }}>
<Plural value={count} zero="no books" one="# book" few="# bookz" other="# books" />
</I18nProvider>
0 books, 1 book, 2 books, 5 books
@kirillku I see, so basically we would have default plural rules:
0: zero 1: one 2: two 3: few 4: many 5+: other
when language specific plural rules aren't available, right?
@tricoder42 this is how i see general rules for plurals:
plural(props) {
switch(props.count) {
case 0:
return props.zero || props.other
case 1:
return props.one || props.other
case 2:
return props.two || props.few || props.other
case 3:
return props.few || props.other
case 4:
return props.few || props.other
// 5+
default:
return props.other
}
}
Also, didn't get what the diffirence between many
and other
, so didn't put it there.
The difference depends on language, but if we do it this way, we should probably define all plural rules.
I'm still deciding between default plural rules or using other
form when no plural rules are loaded. We want to make the component work without I18nProvider. However, when component returns incorrect text because of default plural form, you are forced to use I18nProvider anyway.
@tricoder42 From my point of view, it is ok if the wrong text is returned when no I18nProvider
is used. The only point is that the return value should be readable, because it is better to get 1 books
instead of {count, plural, other {# books}}
.
What do you think about this default behavior:
plural(props) {
if (props.count === 1) {
return props.one || props.other
}
return props.other
}
It uses only other
and one
. So it will be already enough for English. And other languages will get wrong plural forms, but it will be still readable.
Closing as a stale issue. Feel free to reopen with updates
I'm not sure is it bug or current behavior, but when there are no catalog passed to
I18nProvider
or no translation specified inmessages
, instead of showing default values, it shows translations strings inside the application.example:
=>
should be something like:
Seems like it works properly only when
<I18nProvider development={dev} catalogs={{}} />
.