Open hworld opened 7 years ago
Nope you can't do this in that way because interpolation in attributes has been deprecated in Vue.js 2.
However, you can use an inline expression or a computed property:
<template>
<div>
<!-- Inline expression. -->
<p :title="$gettext('Translate this')">Foo bar.</p>
<!-- Computed property. -->
<p :title="myTitle">Foo bar.</p>
</div>
</template>
<script>
export default {
computed: {
myTitle () {
return this.$gettext('Translate this')
},
},
}
</script>
Ah, I didn't even think of the fact that I can use "$gettext" within the template like that. That's perfect. Thanks so much!
The computed property example works but the inline expression is not working for me. The make file command is not capturing it as a translation.
vue-gettext 2.0.8 Mac Os Sierra 10.12.3 gettext 0.19.8.1 easygettext 1.2.2
@kemar Do you have an example of the inline expression working? If so I'll dig deeper into what I might be doing wrong.
@trainiac yes you're right: the Makefile target does not extract translations for inline expressions.
I'll need to have a depper look at gettext-extract
or xgettext
to see what would be the best way to fix this.
Meanwhile you can use a computed property to circumvent the problem.
The only thing I could think of to solve this problem was to compile all templates using the vue template compiler and then crawling over that build folder to extract the strings. =\
I have no easy solution for this problem yet.
gettext-extract
(as it is currently) will only works with custom tags or attributes.
And xgettext
will not parse the non JavaScript part of single-file components with a .vue
extension.
The most likely "good enough" solution would be to implement something like this and feeding xgettext
with the results of a e.g. a sed
command. That could raise other problems like loosing the context of the files etc.
In my project I use this method: a.html
<input type="text" :placeholder="'Email address' | translate"/>
Then
gettext-extract --startDelimiter "" --endDelimiter "" --output a.pot a.html
It grabs my sting to *.pot file
And my filter:
Vue.filter('translate', value => {
return !value
? ''
: Vue.prototype.$gettext(value.toString())
})
Will it work?
@mazavr it work, man
Ran into this issue as well, FWIW the solution mentioned here by @mazavr does work, however the extraction is really slow this way.
I ended up using a mix of vue-gettext and babel-vue-extractor, and then using msgcat
to concatenate the two.
With a babel.cfg
file like:
[babelvueextractor.extract.extract_vue: **.vue]
And the running something like this
gettext-extract --quiet --attribute v-translate --output translations-gettext.po <source files>
pybabel extract -F babel.cfg --keywords '$gettext' -o translations-babel.po <source files>
msgcat translations-gettext translations-babel.po -o translations.po
Using @alexkiro method I use this bash file to extract and make translations generate_translations.sh
#!/usr/bin/env bash
NODE_BINDIR=../node_modules/.bin
INPUT_FILES=./assets/js
TEMP_BASE=./base.pot
TEMP_EXTRA=./extra.pot
TEMP_MERGED=./merged.pot
OUTPUT_DIR=./assets/langs
export PATH="$NODE_BINDIR:$PATH"
LOCALES=(en_US es_ES re_RE)
GETTEXT_SOURCES=`find $INPUT_FILES -name '*.jade' -o -name '*.html' -o -name '*.js' -o -name '*.vue'`
gettext-extract --quiet --attribute v-translate --output $TEMP_BASE $GETTEXT_SOURCES
pybabel extract -F babel.cfg --keywords '$gettext' -o $TEMP_EXTRA $GETTEXT_SOURCES
msgcat ./base.pot ./extra.pot -o $TEMP_MERGED
LOCALE_FILES=""
for lang in "${LOCALES[@]}"
do
:
PO_FILE=$OUTPUT_DIR/locale/$lang/LC_MESSAGES/app.po
LOCALE_FILES=" $LOCALE_FILES $OUTPUT_DIR/locale/$lang/LC_MESSAGES/app.po "
mkdir -p `dirname $PO_FILE`
if [ -f $PO_FILE ]; then
msgmerge --lang=$lang --update $PO_FILE $TEMP_MERGED
else
msginit --no-translator --locale=$lang --input=$TEMP_MERGED --output-file=$PO_FILE
msgattrib --no-wrap --no-obsolete -o $PO_FILE $PO_FILE;
fi
done
mkdir -p $OUTPUT_DIR
gettext-compile --output $OUTPUT_DIR/translations.json $LOCALE_FILES
rm $TEMP_BASE $TEMP_EXTRA $TEMP_MERGED
for attributes like:
<info-box :title="$gettext('Staff')"></info-box>
In my experience, https://github.com/Polyconseil/easygettext extracts everything now, including Vue templates, ES7 code, and so on. msgmerge etc is not necessary anymore and should be removed from the docs. I'll do it asap.
the current version of easygettext don't extract attributes like
<my-component :my-attribute="$gettext('my translatable string')">[...]</my-component>
that seems to me like a nice addition to easygettext :) Do you think you could come up with a pull request ? Would seem way cleaner than a complex pybabel + GNU gettext + easygettext utilities, don't you think ?
Given that easygettext works with | translate
filter syntax and translate, I have adopted this as the best solution here. While using an expression with attr=":$gettext('Text')" silently "works" in that the translation compiles, easygettext doesn't see this type of text and so that is a dead end.
In using | translate
filter syntax, I found I needed interpolation support so I tweaked my Vue.filter this way:
Vue.filter('translate', function(value, params) {
return !value
? ''
: (params
? Vue.prototype.$gettextInterpolate(value.toString(), params)
: Vue.prototype.$gettext(value.toString()))
});
This allows me to create attribute expressions like this:
<smc-okcancel-dialog :title="'Change User: %{user.usename}' | translate({user})"
Which I find super helpful and awesome. I propose this just be added to vue-gettext and documented as the solution for this problem, since it is requires no additional work to support attributes.
@kwesterfeld The part 'Change User: %{user.usename}'
is still not being extracted when used in a vue
file. Did you manage to get it working? Can you sumbit a PR with a working example?
Hey there! I didn't see in the documentation an answer to this. I'm working on switching away from angular and therefore angular-gettext. With that lib you can translate attributes of html elements like so:
<div title="{{ 'Translate this' | translate }}">
.Is the solution for vue-gettext to instead call into the vm methods and use a computed property instead or is a similar filter possible? I know that in vue2 filters are a bit discouraged now, though.