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

Translations in attributes #9

Open
hworld opened this issue Feb 21, 2017 · 16 comments
Open

Translations in attributes #9

hworld opened this issue Feb 21, 2017 · 16 comments

Comments

@hworld
Copy link

hworld commented Feb 21, 2017

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.

@kemar
Copy link
Contributor

kemar commented Feb 21, 2017

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>

@kemar kemar closed this as completed Feb 21, 2017
@hworld
Copy link
Author

hworld commented Feb 21, 2017

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!

@trainiac
Copy link
Contributor

trainiac commented Mar 16, 2017

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

@trainiac
Copy link
Contributor

@kemar Do you have an example of the inline expression working? If so I'll dig deeper into what I might be doing wrong.

@kemar
Copy link
Contributor

kemar commented Mar 17, 2017

@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.

@kemar kemar reopened this Mar 17, 2017
@hworld
Copy link
Author

hworld commented Mar 21, 2017

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. =\

@kemar
Copy link
Contributor

kemar commented Mar 22, 2017

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.

@mazavr
Copy link

mazavr commented Dec 28, 2017

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?

@alansoliditydev
Copy link

@mazavr it work, man

@alexkiro
Copy link

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

@drzippie
Copy link

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>

@vperron
Copy link
Contributor

vperron commented Jan 17, 2019

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.

@drzippie
Copy link

the current version of easygettext don't extract attributes like

<my-component :my-attribute="$gettext('my translatable string')">[...]</my-component>

@vperron
Copy link
Contributor

vperron commented Jan 17, 2019

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 ?

@kwesterfeld
Copy link

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.

@kemar
Copy link
Contributor

kemar commented Oct 19, 2019

@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?

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

No branches or pull requests

9 participants