Open pantuchy opened 6 years ago
Have you tried router.app.$gettext('Some text')
? The app
property on the router instance is the Vue instance on which the global gettext methods are available.
This is interesting but I have a similar need for vuex and for a pure js module (messages used by vuelidate-error-extractor). Do you have a solution for these situations?
We're doing this:
gettext.js
:
import Vue from 'vue'
export const interpolate = Vue.prototype.$gettextInterpolate
export default Vue.prototype.$gettext
And in a js
-file:
import gettext from '@helper/gettext'
export default {
mainNav: {
animals: {
itemText: gettext('AnimalsText'),
routeName: 'Animals',
},
...
Does this help?
I tried it, I created gettext.js and then I imported it in the store and I get the error:
cv.js?c148:113 Uncaught TypeError: Object(...) is not a function
.
Did you add the plugin to your Vue instance? The idea assumes that you integrated vue-gettext into your Vue-project already. If yes we need to check more detailed. Maybe you can create a test-repo and share it.
Yes, I integrated vue-gettext with following conf:
Vue.use(GetTextPlugin, {
translations: translations,
availableLanguages: {
en_GB: 'British English',
it_IT: 'Italiano',
pl: 'Polski',
pt: 'Português',
pt_BR: 'Português brasileiro',
},
defaultLanguage: navigator.language.replace('-', '_'),
silent: false,
}
And is working perfectly. Honestly -due to my poor knowledge of js, my background is Python...- I'm, uncertain of what happens when you write Vue.use(...): any instance of Vue will get that plugin from Vue.prototype? that means that if it works I can get also $language in the same way? Could you even use Vue.prototype.$gettext directly? Anyhow I'll come back later with a complete codesandbox example.
I prepared this codesandbox that shows the error I'm getting. In main.js I tried to change the import order so that plugin is loaded before App is read, but the error doesn't change.
Any hint is appreciated.
@sandroden as its name implies, this plugin is thightly coupled to a Vue.js application. All components of an app are sharing the same Vue instance (in your codesandbox it's the one in main.js
).
When you're importing Vue in your gettext.js
file, you're creating another instance of Vue that is not aware of the plugin without $gettext
in its prototype
. That's why your codesandbox shows an error.
As suggested by others, you can find some ways to share the Vue instance and somewhat use the plugin in custom js modules, but you will loose the reactivity that is provided by the component and the directive.
All use cases supported by the plugin are covered in the documentation.
My codesandbox sample was in fact the attempt to implement @escapedcat 's suggestion. Reactivity may not be an issue in mutations and actions at least. I just realized that store has an instance of vue as store._vm
, that can be used at least to translate messages from within an action. The case that is left unresolved to me is a message list used in a separate file. As an example I use vuelidate-error-extractor to display validation error messages.
There is another easy working way to do this: you can push this.$gettext object into a vuex store as a state variable and then use it there.
Any solution to this? how could we use gettext in a completely separate js file?
Any solution to this? how could we use gettext in a completely separate js file?
I recommend to use i18n for Vue projects. It also has Nuxt Js module
Well, I'm actually switching from i18n. gettext is the standard way of handling translations in linux and has automatic extraction of string. I don't really understand why the vue community opted for a different approach.
Besides lacking the automatic extraction of string, i18n is more verbose, since we have to write message.key everywhere and it makes more difficult to non-programmers translators to translate the files. AFAIK, there is no software like poedit that allows a non technical person to translate the strings.
This might be helpful to people here: https://github.com/Polyconseil/vue-gettext/issues/51#issuecomment-581567628
There's another way of doing this by using a "lazy-string" technique
JavaScript will try to convert objects into string before rendering them to the UI (You can often see something like [Object object]
)
Taking advantage of that, we can make a custom object, and then override the toString() method with the gettext function, so it only runs when rendered
class LazyString {
constructor(msgid, locale) {
this.toString = translate.gettext.bind(translate, msgid, locale)
}
}
const gettextLazy = (msgid, locale) => new LazyString(msgid, locale)
In any files, you can just use it
const YOUR_CONST = {
HELLO: gettextLazy("Hello World!")
}
And that should work with your components
<template>
<div>{{ YOUR_CONST.HELLO }}</div>
</template>
This should also work for SSR too, if you use Nuxt, please make sure the language is set properly before the page rendered, there're hooks that run after plugin initialization and before rendering, you should set your language in those hooks from your cookies, user's settings or whatever, good luck
Hello. Please advise, how to run translation functions like (gettext, ngettext and etc. ) in custom js file? For example Vue-Gettext is installed and initiated in main.js file, everything is working fine, but if I want to use gettext functions in router.js file, functions are not working, I have tried:
Vue.$gettext('Some text')
this.$gettext('Some text')
Vue.prototype.$gettext('Some text')
Nothing works. In Router file I am setting titles for each page, and I wish, that they will be available for translating. Please help. Thank you.