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

[Feature request] - Override of the getChoiceIndex function should be available via options object on initialization #464

Closed
AndrewBogdanovTSS opened this issue Nov 15, 2018 · 13 comments
Labels
good first issue Good for newcomers

Comments

@AndrewBogdanovTSS
Copy link

I use vue-i18n via another lib nuxt-i18n so I doesn't have direct access to the library to override getChoiceIndex method in a clean way as it described in the documentation and my personal opinion is that it looks dirty to to this at all. Instead, what I like is to be able to do override this method via default vue-i18n config object. The syntax is pretty simple:

new VueI18n({
  locale: 'pl', // set locale
  getChoiceIndex(choice, choicesLength) {
     // Custom pluralization code goes here
  }
})

so when using nuxt-i18n module I can simply do:

modules: [ ['nuxt-i18n', {
locales: [...], 
vueI18n: {
   getChoiceIndex(choice, choicesLength) {
     // Custom pluralization code goes here
  }
}
}]]

I think such approach is much more cleaner to use!

@Raiondesu
Copy link
Contributor

Raiondesu commented Dec 14, 2018

@AndrewBogdanovTSS, sorry it took so long... but there it is! 😄

For now you can install it with

npm install --save raiondesu/vue-i18n#master

kazupon pushed a commit that referenced this issue Dec 16, 2018
…or options (closes #464) (#482) by @Raiondesu

* improvement(getChoiceIndex): make getChoiceIndex overridable

This provides better pluralization customization. :D

* update(docs): fit the new functionality

* build(dist): generate dist files

* revert(dist): unbuild files to correspond with guidelines

* docs(pluralization): fix typo

* improvement(test/unit): add test case for custom pluralization

* docs(pluralization): remove unnecessary code from new pluralization example

* update(types): add types for the new pluralization feature

* ⚡improvement(types): remove duplicate type definitions

Replace Number and Date format options with standard TS `Intl` types.

* ⚡improvement(tests): Let types allow to pass getChoiceIndex into options

* ⚡improvement(index): Set getChoiceIndex for current instance from opts

Fixes #464

* 🐛fix(types): fix type aliases for format options

* ⚡improvement(index): allow to pass a pluralization rules map instead

Fixes #464

* 📃docs(api): fix md typo

* ⚡improvement(types/flow): add `pluralizationRules` to the instance types

* 📃docs(pluralization): add the documentation for #464 functionality

* 📃docs(pluralization): fix typo

* ⭐️new(test): add a test case for #464

* 📃docs(pluralization): improve custom pluralization definitions

* ⭐new(test): add a test for backward compatibility with #451 and 8.4.0

* improvement(index): apply the pluralization rule to the instance

For better extensibility.

* 📃docs(api): improve `pluralizationRules` property definition

* docs(pluralization): fix jsdoc comment misplacement

* Revert "⚡improvement(types): remove duplicate type definitions"

This reverts commit 286bc2e.

* ⚡revert(types): Bring back original VueI18n aliases for format options
Raiondesu added a commit to Raiondesu/vue-i18n that referenced this issue Dec 17, 2018
@AndrewBogdanovTSS
Copy link
Author

@Raiondesu is there any ETA on when this will be released in a stable version?

@Raiondesu
Copy link
Contributor

@AndrewBogdanovTSS, see changelog and v8.7.0

@AndrewBogdanovTSS
Copy link
Author

@Raiondesu I still see this page showcases outdated documentation. I believe it should show an example of using pluralizationRules option, right?

@AndrewBogdanovTSS
Copy link
Author

@Raiondesu I tried to pass pluralizationRules option like so:

pluralizationRules: {
      pl: n => n < 2 ? n : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 2 : 3
    }

but looks like this function is not being called at all 🤔

@Raiondesu
Copy link
Contributor

Raiondesu commented Jan 21, 2019

Hmm... 🤔

I tried out the latest build - pluralization seems to work fine for me... What a mystery.

Still, you are perfectly right documentation-wise. @kazupon, how do we update the docs on on the website?

@fibigerg
Copy link

fibigerg commented Feb 22, 2019

Hi, not working for me either with nuxt, vue-i18n on v8.8.2. Am I missing somehting? Thanks @Raiondesu

[
  'nuxt-i18n',
  {
    locales: [{ code: 'en', iso: 'en-US', file: 'en.js' }, { code: 'cs', iso: 'cs-CZ', file: 'cs.js' }],
    strategy: 'prefix_except_default',
    defaultLocale: 'cs',
    langDir: 'lang/',
    vueI18nLoader: true,
    lazy: true,
    vueI18n: {
      pluralizationRules: {
        cs: function(choice, choicesLength) {
          return 0
        },
      },
    },
  },
],

@lukaVarga
Copy link

Hi, I also seem to be facing the same problem as fibigerg (and have pretty much the same config as he does). The custom pluralization rules function isn't being called. The English default one is being used instead. Also on nuxt and vue-i18n v8.8.2.

Any chance you could take a look at what might be the reason @Raiondesu ?

@lukaVarga
Copy link

lukaVarga commented Mar 3, 2019

Ok so upon some further digging, the problem is not in vue-i18n but rather in nuxt-i18n. As you can see here, nuxt-i18n takes the vueI18n options and stringifies them using JSON.stringify. That causes the functions to be removed and just returns an object pluralizationRules: {}.

So here's a nice workaround. Instead of adding pluralizationRules within vueI18n options, you can add a plugin:

export default ({ app }) => {
  app.i18n.pluralizationRules = {
    sl: slovenePluralization
  };
}

function slovenePluralization(number, choicesLength) {
  let option = null;

  if (number === 0) {
    option = 3;
  }

  if (number % 100 === 1) {
    option = 0;
  }

  if (number % 100 === 2) {
    option = 1;
  }

  if (number % 100 === 3 || number % 100 === 4) {
    option = 2;
  }

  if (option === null) {
    option = 3;
  }

  return option > choicesLength ? choicesLength : option;
}

and then you just have to register the plugin with ssr: true:

// nuxt.config.js

module.exports = {
  ...
  plugins: [
    { src: '~plugins/pluralization.js', ssr: true }
    ],
  ...
};

That way it works for SSR as well :)

Hope that helps. cc @fibigerg @AndrewBogdanovTSS

@AndrewBogdanovTSS
Copy link
Author

Thanks for a workaround @lukaVarga. But maybe it's a good point for improvement for nuxt-i18n library itself? Maybe it will logical to log a bug/improvement in their repo, what do you think?

@lukaVarga
Copy link

@AndrewBogdanovTSS can't hurt, I just didn't have time to log it there yesterday. I'll open up an issue 👍

@fibigerg
Copy link

fibigerg commented Mar 6, 2019

Thanks @lukaVarga, the workaround works. It is nice to have it separately in plugin, too.

@bludnic
Copy link

bludnic commented Apr 22, 2019

No need to override VueI18n.prototype.getChoiceIndex . Update nuxt and vue-i18n to latest version, and use pluralizationRules option.

$ npm i --save [email protected]
$ npm i --save [email protected]

plugins/i18n.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)

function slavicPluralization (choice, choicesLength) {
  if (choice === 0) {
    return 0
  }

  const teen = choice > 10 && choice < 20
  const endsWithOne = choice % 10 === 1

  if (!teen && endsWithOne) {
    return 1
  }

  if (!teen && choice % 10 >= 2 && choice % 10 <= 4) {
    return 2
  }

  return (choicesLength < 4) ? 2 : 3
}

export default ({ app, store }) => {
  app.i18n = new VueI18n({
    locale: store.state.locale,
    fallbackLocale: 'en',
    messages: {
      'en': require('~/locales/en.json'),
      'ru': require('~/locales/ru.json')
    },
    pluralizationRules: {
      ru: slavicPluralization
    }
  })
}

nuxt.config.js

plugins: [
  '~/plugins/i18n.js'
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

6 participants