BazingaJsTranslationBundle icon indicating copy to clipboard operation
BazingaJsTranslationBundle copied to clipboard

Translator returns translation keys instead of translations

Open Rikijs opened this issue 5 years ago • 10 comments

Followed documentation and yet have a problem. Translator returns translation keys instead of translations. Full explanation of the issue at hand on StackOwerflow. What am i missing?

Rikijs avatar Sep 28 '18 21:09 Rikijs

the issue is that you have 2 translators in your JS:

  • the global Translator variable defined by your loading of bundles/bazingajstranslation/js/translator.min.js, which is configured with the appropriate translations (loaded from url('bazinga_jstranslation_js'))
  • the instance bundled inside your webpack build when importing bazinga-translator, which is used by your code, but does not have any loaded translations.

stof avatar Oct 01 '18 10:10 stof

Thank you for your comment @stof.

the issue is that you have 2 translators in your JS:

Now i see the problem. So i should use only one translator.

I think that the one i am importing is the way to go. What should be the config in that case?

Am i correct at thinking that includes in base.html.twig <script src="{{ asset('bundles/bazingajstranslation/js/translator.min.js') }}"></script> and <script src="{{ url('bazinga_jstranslation_js') }}"></script> are not needed anymore? Because translator is imported in test.js...

But now i have following error in the console:

ReferenceError: Translator is not defined[Learn More]
bazinga-translator
external "Translator":1
__webpack_require__
bootstrap 2b9bb242f4ffe6caa822:19
./assets/js/test.js
test.js:1
__webpack_require__
bootstrap 2b9bb242f4ffe6caa822:19
<anonymous>
bootstrap 2b9bb242f4ffe6caa822:62
<anonymous>
http://127.0.0.1:8000/build/test.js:1:11

Aside

It works if there is<script src="{{ asset('bundles/bazingajstranslation/js/translator.min.js') }}"></script> in base.html.twig. and <script src="{{ url('bazinga_jstranslation_js', { 'domain': 'TRANSLATION_DOMAIN_NAME', 'locales': 'en,fr,de' }) }}"></script> in test.html.twig. But i guess in this case it is working with wrong translator, is it not?

Please show an example configuration that works with Webpack.Encore. Thank you for your help.

Rikijs avatar Oct 01 '18 16:10 Rikijs

Command yarn encore dev does not return an error. But i get an error in browsers console. I have read available BazingaJsTranslation bundle documentation and issues on github thoroughly, but did not find working solution. Any help with this issue would be greatly appreciated.

Rikijs avatar Oct 04 '18 15:10 Rikijs

@Rikijs <script src="{{ url('bazinga_jstranslation_js', { 'domain': 'TRANSLATION_DOMAIN_NAME', 'locales': 'en,fr,de' }) }}"></script> does not define a translator. It loads the translations in the translator available in Translator. So your suggestion would work well (assuming that you don't use the translator in JS code running on other pages where translations would not be loaded in it of course)

stof avatar Nov 14 '18 16:11 stof

there is no easy way to load the translations into Translator, if you are using it fom webpack, and do not want to have script tags.

you could the what @timwhite sugested here https://github.com/willdurand/BazingaJsTranslationBundle/issues/252#issuecomment-569460207

i have the same problem .. if someone has any sugesions on how to load translations after "import Translator from 'bazinga-translator';" please let us know


this worked for me:

first i used the dump command to dump the translations as json and then i added this in my app.js:

import translator from 'bazinga-translator';

import('../../public/js/bazinga_jstranslation_js/translations/messages/' + document.documentElement.lang).then( function (translations) { translator.fromJSON(translations); } );

drjele avatar Feb 04 '20 16:02 drjele

import Translator from 'bazinga-translator';

(async () => {
  const res = await fetch('/translations/messages.json');
  const json = await res.json();
  Translator.fromJSON(json);
})();

this works via ajax.

st-schneider avatar Feb 17 '20 11:02 st-schneider

Inspired by @bm-stschneider, we can actually bundle this fairly easily in a component (I didn't need the translation on each page).

// ./components/_translator_webpack.js
/* This async loading is required to make the translator work through webpack */
import Translator from 'bazinga-translator';

(async () => {
    const res = await fetch('/translations/messages.json?locales=en,fr');
    const json = await res.json();
    Translator.fromJSON(json);
})();

export default { Translator }

The important bit in that code are the locales I wish to expose via the async call (in my use case, I was fine exposing all the languages and all the keys).

Then your other script (if needed)

import Translator from './_translator_webpack';

Translator.Translator.trans('translation.key')

Schyzophrenic avatar Jul 24 '20 18:07 Schyzophrenic

Still stuck into the same problem, using the NPM package and loading the translations. Documentation lacks a lot and version 4 doesn't work, it complains about the INTL dependency not found!

Anyways, both @Schyzophrenic and @st-schneider solutions doesn't play well because loading in asynchronously, that is the Translation will (most probably) used before the loading complets.

gremo avatar Nov 19 '20 09:11 gremo

@gremo if you want to bundle the translator and translations in your webpack build, the simpliest way is probably to use the dumping command to dump the translations to JSON and import them in your webpack build.

An alternative would be to change the solution from @Schyzophrenic to use a top-level await in the module for the loading of translation, making the module itself async, instead of asynchronously loading translations in a sync module (which indeed causes issues). But this requires using webpack 5 with an experimental feature turned on for now: https://webpack.js.org/configuration/experiments/

stof avatar Nov 19 '20 09:11 stof

I made it work like the following In the twig file, put in your scripts the needed call as described in doc

<html lang="{{ app.request.locale|split('_')[0] }}">
<head>
    ...
    <script src="{{ asset('bundles/bazingajstranslation/js/translator.min.js') }}"></script>
    <script src="{{ url('bazinga_jstranslation_js', { 'domain': 'DOMAIN_NAME', 'locales': 'MY_LOCALE' }) }}"></script>
</head>
<body>
   <div id="app"></div>
   {{ encore_entry_script_tags('app') }}
</body>
</html>

create a small translator.[js|ts] file

//translator.[js|ts]
module.exports = global.Translator

and in your js files, you can then call it like that

//app.[js|ts]
const Translator = require('./translator');
Translator.trans('id-to-translate')

yalit avatar Sep 23 '22 11:09 yalit