Closed Grawl closed 5 years ago
The need of a better pluralization is there, but I think this is a bit cumbersome.
Wouldn't it be easier if we just let the translations to use the Laravel's pluralization format? 'apples' => '{0} There are none|[1,19] There are some|[20,Inf] There are many',
.
IMO, it's simpler and more clear. Also, we could reuse Laravel labels... :clap:
@skyrpex looks good! I like this format.
And, since Laravel supports Vue out of the box, it's good to be compatible.
Maybe we could create some sort of abstraction and let the user to register custom pluralization plugins (just like custom formatters)?
// The simplest implementation
Vue.config.i18nPluralizer = (string, count) => {
const parts = string.split('|');
if (count === 1) {
return parts[0];
}
return parts[1];
};
@skyrpex I think better to include it into vue-i18n
. Pluralization should be simple. smart-plurals
do.
There would be a default implementation for sure, but having the power to customize it is priceless.
Why should we customize it? There is a languages, each have it's rules.
Letting the "pluralizer" to be customizable would make the users able to choose whatever pluralization method they need. This means one could use Laravel's syntax ('apples' => '{0} There are none|[1,19] There are some|[20,Inf] There are many'
) or something that uses smart-plurals, like:
{
apples: {
singular: 'There is an apple',
few: 'There are {count} apples',
plural: 'There are so many apples',
}
}
Sounds good. I agree.
How about http://formatjs.io? Having this as vue component would be awesome!
@xpepermint looks cool!
That library looks awesome, I must admit! It handles formatting and pluralization with a single pass, though. The public vue-i18n API should change, then?
@kazupon what do you think about ICU format? Is there a chance that we get this into vue-i18n
? That would be super awesome :).
A quick and dirty proposal/example - it would be great not to depend on Intl and intl-messageformat
(i think I saw a version of vue-intl
package which implements this) because you need a polyfill for old browsers.
import * as merge from 'lodash.merge';
import IntlMessageFormat from 'intl-messageformat';
export class I18n {
locale: string;
messages: any;
formats: any;
/*
* Class constructor.
*/
constructor ({
locale = 'en-US',
messages = {},
formats = {}
}: {
locale: string,
messages?: any,
formats?: any
}) {
this.locale = locale;
this.messages = messages;
this.formats = merge(IntlMessageFormat.formats, formats);
}
formatNumber (value: number, options: any = {}) {
let {format, ...props} = options;
props = merge(this.formats.number[format], props);
return new Intl.NumberFormat(this.locale, props).format(value);
}
formatDate (value: number | Date, options: any = {}) {
let {format, ...props} = options;
props = merge(this.formats.date[format], props);
return new Intl.DateTimeFormat(this.locale, props).format(value);
}
formatTime (value: number | Date, options: any = {}) {
let {format, ...props} = options;
props = merge(this.formats.time[format], props);
if (Object.keys(props).length === 0) {
props = this.formats.time.short;
}
return new Intl.DateTimeFormat(this.locale, props).format(value);
}
formatMessage (message: string, vars: any = {}) {
return new IntlMessageFormat(message, this.locale, this.formats).format(vars);
}
}
Here is another alternative: http://i18njs.com/#pluralisation
@xpepermint Thanks for your referennce link! 👍 Looks great to me!!
I think that i want to support translation based on ECMA-402. https://github.com/kazupon/vue-i18n/issues/14
In vue-i18n v5.0 later, I'll plan to support it and full-scrach development.
ref: vue-intl https://github.com/learningequality/vue-intl
Yeah, I tried vue-intl
, also their vue2
branch but some methods just don't work and I feel there's a lack of interest for fixing it. I've created vue-translated for now because we have to deploy our platform in a month.
Hurray for the decision about ECMA-402! Five Points from Gryffindor :)!
If I go back to the actual theme of this thread ... I believe that pluralization is something that this package should allow for all languages. This is something that currently prevents us from using this package in our projects. What are your plans about that?
I see Intl.DateFormat and Intl.NumberFormat have made it into v7, thanks ❤️.
What's holding back (ICU) MessageFormat (e.g. via intl-messageformat) as suggested by @xpepermint? Did you decide to not pursue this furthor in favor of having implementors use Custom Formatting as shown in the custom formatting example?
It's actually fairly straight-forward to implement pluralization and relative dates manually. I personally did exactly that, because my whole app takes up about 60K and the RFC/Intl shenanigan takes up 20K per messageformat
and relativeformat
+ another 60K for Intl polyfill, not to mention whatever integration code you still have to write. If you need something pragmatic, then it makes sense to just bundle up your locales along with pluralization functions (see https://github.com/svenfuchs/rails-i18n/tree/master/lib/rails_i18n/common_pluralizations
) and whatever locale-specific helpers you need and dynamically import them on locale switch. Thanks to Webpack that's a breeze. The relative dates feature is just a single common function that builds on top of that. Here's my quick and dirty plugin that takes up just 1.5K gzipped https://gist.github.com/krukid/eb4aea19721ed360d27ec4eea818320f, the rest is loaded by loadLocale()
when invoked. You can even wrap this up nicely in a vue-router
middleware that will block until non-packaged locale is being pulled.
Is it already implemented?
Nice implementation has Yii2 framework Yii2 guide
I like the smart plurals approach from @Grawl, I hope this could be added.
Any plans to implement this feature?
I find it interesting that a translation system would propose pluralization that only works in English. This kind of defeats the purpose of translating... And this ticket has been open for almost two years.
In other words, are you guys motherfucking NUTS? You reached version 7 without noticing this?! Wake the fuck up guys...
Thanks :heart:
I didn't dig too much into this, but I think you can already implement your own formatter.
@kazupon Any plans to implement this feature?
In the future, I'll implement vue-i18n with full-scratch. In the timing, I might plan to adopt ICU format.
We're using vue-i18n too, and as we look at expanding to other platforms and languages, this feature would really help us in implementing without superfluous plugins.
So there is still no possibility to work with pluralization in other languages except English?
Unfortunately below solution doesn't cover this syntax:
'apples' => '{0} There are none|[1,19] There are some|[20,Inf] There are many'
It only supports simple plural forms discovered based on getPluralIndex
function. I also had to do my own formatting as BaseFormatter isn't exported...
class PluralizableMessageFormatter {
constructor(locale) {
this.locale = locale;
}
interpolate(message, values) {
// This is the greatest hack in history
if (!values || !values.hasOwnProperty('number')) {
return [message];
}
const index = getPluralIndex(this.locale, values.number);
const template = message.split('|')[index];
return [
Object
.keys(values)
.reduce((result, key) => result.replace(`{${key}}`, values[key]), template.trim())
];
}
}
You ignore $tc
function all together and instead you use $t
with number
key...
{{ $t('messages.years_old', { number: contractor.age, age: contractor.age }) }}
The number key imitates second argument in normal trans_choice
function.
You also need to create getPluralIndex.js
copied from \Illuminate\Translation\MessageSelector::getPluralIndex
.
https://gist.github.com/3amprogrammer/56e543472850923936d2b5f2194d6640
@kazupon, would you accept potential PR that implements this feature in an extendable way?
I'd propose simething like an ability to override a function on VueI18n prototype that would behave somewhat similar to fetchChoise.
This would not break any current logic while also allowing users to define custom behaviour for plurals, for example.
Just to clarify if it makes sense for me to do it...
P.S. As an additional argument - this issue is 2 years old and there were multiple somewhat breaking updates in this time period. Maybe this needs to be implemented already?..
Ah, I'll do it anyway...
Everyone in need can install the updated lib from my github for now:
npm install raiondesu/vue-i18n#master
In English, pluralization looks simple: one and many. But it's not too simple for Russian language. And there is some other languages.
i18n
means Internationalization.I suggest to use something better for pluralization into
$tc()
/Vue.tc()
.For example,
smart-plurals
.Now I using it with Vue like this:
So I can now write different amount of plural forms for different languages in one format:
singular | plural
for English orsingular | few | plural
for Russian for example.And then just
pluralize('key', value, Vue.config.lang)
as a function in JSAnd
{{ $t('key') | pluralize(computedProperty()) }}
as a filter in templates:Other sources you can see in this repo.