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

TypeError: Cannot read property '$i18n' of undefined #259

Closed
lzxb opened this issue Nov 27, 2017 · 13 comments
Closed

TypeError: Cannot read property '$i18n' of undefined #259

lzxb opened this issue Nov 27, 2017 · 13 comments

Comments

@lzxb
Copy link
Contributor

lzxb commented Nov 27, 2017

vue & vue-i18n version

ex: ^2.5.3,^7.3.2

Reproduction Link

Steps to reproduce

  • Error: TypeError: Cannot read property '$i18n' of undefined
export default {
    data () {
        const $t = this.$t;
        return {
            msg: $t('msg')
        };
    }
};
  • Normal
export default {
    data () {
        const $t = this.$t.bind(this);
        return {
            msg: $t('msg')
        };
    }
};

What is Expected?

export default {
    data () {
        const $t = this.$t;
        return {
            msg: $t('msg')
        };
    }
};

What is actually happening?

This Not equal to component instance

/* @flow */

export default function extend (Vue: any): void {
  Vue.prototype.$t = function (key: Path, ...values: any): TranslateResult {
    const i18n = this.$i18n
    return i18n._t(key, i18n.locale, i18n._getMessages(), this, ...values)
  }

  Vue.prototype.$tc = function (key: Path, choice?: number, ...values: any): TranslateResult {
    const i18n = this.$i18n
    return i18n._tc(key, i18n.locale, i18n._getMessages(), this, choice, ...values)
  }

  Vue.prototype.$te = function (key: Path, locale?: Locale): boolean {
    const i18n = this.$i18n
    return i18n._te(key, i18n.locale, i18n._getMessages(), locale)
  }

  Vue.prototype.$d = function (value: number | Date, ...args: any): DateTimeFormatResult {
    return this.$i18n.d(value, ...args)
  }

  Vue.prototype.$n = function (value: number, ...args: any): NumberFormatResult {
    return this.$i18n.n(value, ...args)
  }
}
kazupon pushed a commit that referenced this issue Dec 14, 2017
* bug(extend) Fix this not found

* 👕test(issues) featrue #258 test
@kazupon kazupon closed this as completed Dec 14, 2017
@lakb248
Copy link

lakb248 commented Jun 19, 2018

@kazupon I think there is no need to bind this to vue instance, this makes it impossible to bind this to other object, which make it impossible to customize translate function, for example:

/*
Monkey-patches vue-i18n's pluralization support. The original pluralization
uses "|" (pipe) character to separate singular and plural translations.
This is not robust enough; we explicitly define "zero", "one" and "other" translations for pluralization.
*/
// TypeError: Cannot read property '_t' of undefined reported!!!
import * as mappings from '../localization/mappings';

export function patchPluralization(vue) {
  if (typeof vue.prototype.$t === 'function') {
    // cannot override $tc because it is readonly by the declear in vue-i18n
    vue.prototype.$tc2 = function (key, count, values) {
      const translate = vue.prototype.$t;
      const mapping = mappings[key];
      if (typeof mapping === 'object') {
        if (count === 1 && mapping.one) {
          return translate.call(this, `${key}.one`, values);
        } else if (count === 0 && mapping.zero) {
          return translate.call(this, `${key}.zero`, values);
        } else {
          return translate.call(this, `${key}.other`, values);
        }
      } else {
        return translate.call(this, key, values);
      }
    };
  }
}

So is there any possible to make the implemention back to the old way.

And, I think there is no necessary to guarantee this equal to component instance, no matter how people write the code. This should be guaranteed by the coder.

@kazupon kazupon reopened this Jun 22, 2018
@kazupon
Copy link
Owner

kazupon commented Jun 22, 2018

As @lakb248 said, #260 was caused some issues (#306 and #268).
For this reason, I had been reverted this fix.

In the same way as the previous, you need to guarantee this context equal to component instance.

@kazupon kazupon closed this as completed Jun 22, 2018
qkdreyer added a commit to qkdreyer/vue-i18n that referenced this issue Jul 2, 2018
kazupon#260 was referenced twice, but this is fixing kazupon#259 and reverting kazupon#260
kazupon pushed a commit that referenced this issue Jul 3, 2018
#260 was referenced twice, but this is fixing #259 and reverting #260
@cn-xufei
Copy link

Problems still exist.
"vue-i18n": "^8.0.0"

@kevinrodriguez-io
Copy link

Same problem here with Nuxt on 8.8.0

@denisinvader
Copy link

it's very annoying, especially in render functions. I have to write

const $t = key => this.$t(key);
// or
const $t = this.$t.bind(this);

instead of

const { $t, /* necessary props and data */ } = this;

@jebarjonet
Copy link

it's 2020 and still can't

const { $t } = this;
// or
const callback = $t => $t('key')
callback(this.$t)

all other libraries I use work this way ($route, $store, etc.) but not $t

@HansHammel
Copy link

same for me

1 similar comment
@rano1996
Copy link

same for me

@alexvoedi
Copy link

still does not work

@vivekpd15
Copy link

+1

@rohit-orca
Copy link

Still not working for me

@asmirbe
Copy link

asmirbe commented May 6, 2021

Still not working in 2021

@ghost
Copy link

ghost commented May 12, 2021

Still not working in 2021

Have you found a solution?

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

No branches or pull requests