Jump to content

Fluency - The complete translation enhancement suite for ProcessWire


FireWire

Recommended Posts

  • 2 weeks later...

I just started using it on the client project I mentionned a while ago and it's working amazingly, thank you so much for your hard work !

I have one suggestion / request though: could there be a way to add a string at the end of the translation automatically ? Something like "(translated with DeepL)". Ideally as an option per text field ?

I'm seeing from the source code that ___executeData() is hookable, would you suggest to go this way ? Editing the returned json ?

Thank you in advance for your feedback / help.

Link to comment
Share on other sites

14 hours ago, monollonom said:

I just started using it on the client project I mentionned a while ago and it's working amazingly, thank you so much for your hard work !

I have one suggestion / request though: could there be a way to add a string at the end of the translation automatically ? Something like "(translated with DeepL)". Ideally as an option per text field ?

I'm seeing from the source code that ___executeData() is hookable, would you suggest to go this way ? Editing the returned json ?

Thank you in advance for your feedback / help.

It would be pretty complex to create settings for that in the module config on a per-field basis and I think it might be too much of an edge case to implement in the module directly so I think hooking would be your best bet on this. Using `addHookAfter();` is the way to go.

Just remember to test the output of `___executeData()` as it returns different types of data depending on the request, see each case in the switch statement in the `___executeData()` method. Here's some quick info that might help you get up to speed more quickly.

All of the return values from `___executeData()` have the same data structure for predictability when used. At the very least each return value has `data` and `httpStatus` properties/values. A good way to make sure you are dealing with a translation is to decode the JSON (we'll say it's assigned to $decodedResponse), and then look for `$decodedResponse->data->translations;`. If the `translations` property exists in `data` then you know it's a translation. You would want to append your string to `$decodedResponse->data->translations[0]->text;`, encode `$decodedResponse` again, then return the modified JSON..

I'm not sure how you would be able to detect what field has been translated though because the return data from `___executeData()` doesn't contain any field name so your hook would append to all multi-language fields. Let me know if you can't find a workaround for this and I'll see if I can help.

Dunno if that is what you were looking for but hope it helps!

  • Thanks 1
Link to comment
Share on other sites

  • 2 months later...

I’m not quite sure if this is of interest for anyone and if this is the right forum for my post, but I got the client request to build a module extension for Fluency which translates all the text fields in a page with only one click. The module is not really ready for public (or the modules section), as it has no config page yet and was only tested in one ProcessWire installation, but maybe it is useful as a starting point for anyone who is in the same situation as me:

https://github.com/robertweiss/ProcessTranslatePage

The module checks for fluency-translate permissions and adds a ›Translate and save‹-button to the edit-page. It supports all core language fields, Repeater, FieldsetPage the pro modules Repeater Matrix, Combo and Functional Fields.

Caution: for now, the (language-)settings have to be manually edited in the hookPageSave-Method (Lines 64–69). 

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

On 9/24/2021 at 11:13 AM, robert said:

I’m not quite sure if this is of interest for anyone and if this is the right forum for my post, but I got the client request to build a module extension for Fluency which translates all the text fields in a page with only one click. The module is not really ready for public (or the modules section), as it has no config page yet and was only tested in one ProcessWire installation, but maybe it is useful as a starting point for anyone who is in the same situation as me:

https://github.com/robertweiss/ProcessTranslatePage

The module checks for fluency-translate permissions and adds a ›Translate and save‹-button to the edit-page. It supports all core language fields, Repeater, FieldsetPage the pro modules Repeater Matrix, Combo and Functional Fields.

Caution: for now, the (language-)settings have to be manually edited in the hookPageSave-Method (Lines 64–69). 

I had initially written off mass translation because after seeing the time it took to translate one or two fields I thought it could be a big holdup for the user. Have you run into any situations where a whole page runs into problems?

This is really awesome work!

Link to comment
Share on other sites

Thank you, this would not be possible without your excellent module!

I just pushed a new version to Github. The module got some additional features:

  • A config page where you can exclude templates and toggle whether you want to overwrite already existing translations
  • The language selection now uses the settings made in the Fluency config instead of having to configure it twice ? 
  • Support for more than one target language (I never needed that but thought it would be nice to have in the future)
  • Support for the ProField Table

About the performance: I share your concerns, but my client still forced me to do it ? The largest page I tested had 63 fields (25 textfields, 14 file-descriptions, 24 richtext-fields) and took about a minute to translate, so you really have to take care of the php timeout-settings. To bypass that, I added a small external translate-pagetree script to the repository which can be used in the command line, so you can batch-translate multiple parts of the website (or all of it) at once. As this is not tested very well, a database-backup is recommended before trying!

  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...

are there any known issues with pw-installations inside a folder?

It works for me on a website like domain.com but not on pw-installation like domain.com/_temp/
I get this errors on a backend pageload

fluency_tools.js:60 POST https://domain.com/_tmp/fluency/data/ 404
moduleRequest	@	fluency_tools.js:60
(anonymous)	@	fluency.js:579
load (async)		
(anonymous)	@	fluency.js:576
VM287:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.xhr.onload (fluency_tools.js:53)
xhr.onload	@	fluency_tools.js:53
load (async)		
moduleRequest	@	fluency_tools.js:52
(anonymous)	@	fluency.js:579
load (async)		
(anonymous)	@	fluency.js:576


@FireWire you hardcoded the paypalme-PNG-Url into FluencyConfig.php (line:365). It's broken. 
/Fluency/img/paypal_me.png  > /Fluency-Translation-main/img/paypal_me.png

Link to comment
Share on other sites

On 10/29/2021 at 10:42 AM, ngrmm said:

are there any known issues with pw-installations inside a folder?

It works for me on a website like domain.com but not on pw-installation like domain.com/_temp/
I get this errors on a backend pageload

fluency_tools.js:60 POST https://domain.com/_tmp/fluency/data/ 404
moduleRequest	@	fluency_tools.js:60
(anonymous)	@	fluency.js:579
load (async)		
(anonymous)	@	fluency.js:576
VM287:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.xhr.onload (fluency_tools.js:53)
xhr.onload	@	fluency_tools.js:53
load (async)		
moduleRequest	@	fluency_tools.js:52
(anonymous)	@	fluency.js:579
load (async)		
(anonymous)	@	fluency.js:576


@FireWire you hardcoded the paypalme-PNG-Url into FluencyConfig.php (line:365). It's broken. 
/Fluency/img/paypal_me.png  > /Fluency-Translation-main/img/paypal_me.png

Added a fix for the PayPalm img. Thanks for mentioning. Will be included in the next release.

I hadn't anticipated an installation in a subfolder. The module creates an admin page when installed and that page's URL is an endpoint for the JavaScript on the page to make AJAX calls to when getting/sending translation data. The JS assumes that this URL will be at the root level. The JavaScript can't tell if the site is in a subdirectory. I don't know how to code the JavaScript to figure that out since it is separate from the CMS and the module which can tell what the full proper URL is but the JS doesn't have a way to get that info. There is probably a way to solve this problem but it will take a little investigating.

There is a quick and dirty solution that would fix this issue for you right now. That would be to go into the module directory, navigate to /src/js/ and then edit fluency_tools.js to point to the full URL you need by changing line 32.

From this: winLoc.pathname.split('/')[1] + '/fluency/data/'
To this: winLoc.pathname.split('/')[1] + '/_temp/fluency/data/'

That will let the JS know where to get/send translation data. If/when you need to move your PW site to the root directory then change it back to the original value.

Let me know if that works for you.

  • Thanks 1
Link to comment
Share on other sites

Thanks @FireWire
Actually the folder is already showing up in the error message above. When i do your quick fix i get this:  

fluency_tools.js:60 POST https://domain.com/_temp/_temp/fluency/data/ 404
moduleRequest @ fluency_tools.js:60
(anonymous) @ fluency.js:579
load (async)
(anonymous) @ fluency.js:576
VM752:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.xhr.onload (fluency_tools.js:53)
xhr.onload @ fluency_tools.js:53
load (async)
moduleRequest @ fluency_tools.js:52
(anonymous) @ fluency.js:579
load (async)
(anonymous) @ fluency.js:576

 

Link to comment
Share on other sites

25 minutes ago, ngrmm said:

Thanks @FireWire
Actually the folder is already showing up in the error message above. When i do your quick fix i get this:  

fluency_tools.js:60 POST https://domain.com/_temp/_temp/fluency/data/ 404
moduleRequest @ fluency_tools.js:60
(anonymous) @ fluency.js:579
load (async)
(anonymous) @ fluency.js:576
VM752:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.xhr.onload (fluency_tools.js:53)
xhr.onload @ fluency_tools.js:53
load (async)
moduleRequest @ fluency_tools.js:52
(anonymous) @ fluency.js:579
load (async)
(anonymous) @ fluency.js:576

 

Go to the Fluency module configuration page, then click on the "Translation" link in the menu bar. What is the URL of the page that loads?

Link to comment
Share on other sites

7 minutes ago, FireWire said:

Go to the Fluency module configuration page, then click on the "Translation" link in the menu bar. What is the URL of the page that loads?

https://domain.com/_tmp/processwire/fluency/

 

Link to comment
Share on other sites

6 minutes ago, ngrmm said:
https://domain.com/_tmp/processwire/fluency/

 

Okay now I got it. That is the URL that needs to be in the JS file I mentioned. In that JS it does it's best to parse the URL, get the admin slug, then build the request URL.

If you revisit that code in fluency_tools.js  set the value of requestUrl to where it should be able to send requests to the module. It should look like this:

var moduleRequest = function(requestData, callback) {
  var winLoc = window.location,
      params = [],
      requestUrl = 'https://domain.com/_tmp/processwire/fluency/data/'
      // requestUrl = winLoc.protocol + '//' +
      //              winLoc.host + '/' +
      //              winLoc.pathname.split('/')[1] + '/fluency/data/'

    // ... ommitted for brevity ...
}

If you move to production and ProcessWire is being served from the root directory then change this back.

  • Like 1
Link to comment
Share on other sites

9 minutes ago, FireWire said:

Okay now I got it. That is the URL that needs to be in the JS file I mentioned. In that JS it does it's best to parse the URL, get the admin slug, then build the request URL.

If you revisit that code in fluency_tools.js  set the value of requestUrl to where it should be able to send requests to the module. It should look like this:

var moduleRequest = function(requestData, callback) {
  var winLoc = window.location,
      params = [],
      requestUrl = 'https://domain.com/_tmp/processwire/fluency/data/'
      // requestUrl = winLoc.protocol + '//' +
      //              winLoc.host + '/' +
      //              winLoc.pathname.split('/')[1] + '/fluency/data/'

    // ... ommitted for brevity ...
}

If you move to production and ProcessWire is being served from the root directory then change this back.

it works! thanks a lot

  • Like 1
Link to comment
Share on other sites

On 11/11/2020 at 8:29 PM, FireWire said:

Unfortunately I haven't localized the UI yet but that is the next priority item on my list. If you have your primary language set as German and the other language as English, the translation link will still say "Translate from English" but it will still translate from German to English. Right now this issue is purely aesthetic. Here's the language translating from German to English but the translate link saying the wrong text.

868413029_Screenshotfrom2020-11-1109-35-00.png.311e4b7a9ca2e4558d012ab18b451e60.png

If you would like to change these now so you don't have to wait for a module upgrade, you can update the text strings located on the following lines in these JS files:

Fluency/src/js/fluency.js
153
160
216
473
476
490

Fluency/src/js/fluency_language_translator.js
108
168

By changing the text there the module will then fit your setup. Like I mentioned above, I'm working on having this behave correctly out of the box!

I think that due to almost-impossibility to change Processwire default language it's not necessary to explicitly name the language from which the text will be translated. It's enough to change all "Translate from English" phrases to just "Translate".

Link to comment
Share on other sites

On 11/4/2021 at 6:36 PM, theoretic said:

I think that due to almost-impossibility to change Processwire default language it's not necessary to explicitly name the language from which the text will be translated. It's enough to change all "Translate from English" phrases to just "Translate".

I am finishing the next release right now and will be pushing a new version. In this version you can customize all Fluency UI strings for any default language, using the translation service if desired.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...

Thank you for the brilliant work, I'm implementing it on a school website.
I must do something wrong though because there are no available languages to setup in the module.
I followed the PW and your module instructions:

  • Enabled the multi language core modules
  • Added an additional language to test (on top of the default)
  • Edited the Home page for the language URLs
  • Changed page name, text and textarea fields to multi language

Now everything seems to work as expected but inside the Fluency (and TranslatePage) settings there are no languages showing up at all.
Can anyone enlighten me what step I missed?
I'm on PW 3.0.191 dev - Fluence 0.3.2 - local AMPPS with PHP 7.3.11

Screenshot 2021-12-30 at 15.50.33.png

Link to comment
Share on other sites

1 hour ago, Jozsef said:

Thank you for the brilliant work, I'm implementing it on a school website.
I must do something wrong though because there are no available languages to setup in the module.
I followed the PW and your module instructions:

  • Enabled the multi language core modules
  • Added an additional language to test (on top of the default)
  • Edited the Home page for the language URLs
  • Changed page name, text and textarea fields to multi language

Now everything seems to work as expected but inside the Fluency (and TranslatePage) settings there are no languages showing up at all.
Can anyone enlighten me what step I missed?
I'm on PW 3.0.191 dev - Fluence 0.3.2 - local AMPPS with PHP 7.3.11

Screenshot 2021-12-30 at 15.50.33.png

Hmmmm, interesting. Can you confirm the following:

  • The "DeepL API Key" field has your API key entered and that it says "API key validated" below it?
  • Under "DeepL API Account Usage For Current Billing Period" it shows values for Character Limit, Characters Translated, Characters Remaining, and Total Usage? (It is OK if Characters Translated is 0 and Total Usage is 0%)

The Source/Destination Languages are taken from DeepL so this is the first step to make sure that module can connect to their service. I haven't tested this on the dev branch, but I don't believe there are any changes substantial enough to affect Fluency.

 

Link to comment
Share on other sites

On 12/30/2021 at 9:25 PM, Jozsef said:

Yes, the API key validated label is there and it displays 0 for usage, as expected.

 

Next would be to check the ProcessWire logs under Setup > Logs > exceptions, and Setup > Logs > errors to see if there are any PHP errors since it looks like Fluency is able to connect to DeepL.

 

Link to comment
Share on other sites

There must be something on my local machine, I uploaded it to the dev server and it works straight away. I configured it and got busy translating. Thanks for the help and for the great module! I tested DeepL's translation quality with my native language and it blew my mind. Multilingual sites are now really a breeze to create.

  • Like 2
Link to comment
Share on other sites

23 hours ago, Jozsef said:

There must be something on my local machine, I uploaded it to the dev server and it works straight away. I configured it and got busy translating. Thanks for the help and for the great module! I tested DeepL's translation quality with my native language and it blew my mind. Multilingual sites are now really a breeze to create.

That was something I considered after I posted that message. I use Docker for development and for some reason if I am connected to a VPN then DeepL fails to connect and it causes PW to not load admin pages. It is probably a networking configuration in the Docker image. This may be an issue that could exist with some dev environments, but that's just a semi-educated guess haha.

Glad you are enjoying the module! Please let me know if you experience any issues. The next version is coming out soon and it will be going from alpha to beta version and have a bunch of new features. Any feedback is greatly appreciated!

Link to comment
Share on other sites

4 minutes ago, FireWire said:

The next version is coming out soon and it will be going from alpha to beta version and have a bunch of new features.

Sounds good, I'll keep an eye out! Thanks again.

  • Like 1
Link to comment
Share on other sites

  • 4 weeks later...

I tried to follow examples from earlier in this topic to achieve the following in my template files.
The goal would be to save characters for the client and only translate content that is required.

Example:
- Check if $page->headline is available in the user's language
- If not, translate it and save it

I could get it to work with my limited PHP knowledge, this is the code I tried:

$lang = $user->language;
$page->of(false);
$local_headline = $page->headline->getLanguageValue($lang);
if (!$local_headline) {
  $fluency = $modules->get('Fluency');
  $translate = $fluency->translate('en', $page->headline->getLanguageValue($lang), $lang->name);
  echo $translate;
  $page->headline = $translate;
  $page->save("headline");
}
$page->of;

The error I'm getting is:
Undefined variable: message in /modules/Fluency/engines/DeepL.class.php on line 172

Link to comment
Share on other sites

3 minutes ago, Jozsef said:

I tried to follow examples from earlier in this topic to achieve the following in my template files.
The goal would be to save characters for the client and only translate content that is required.

Example:
- Check if $page->headline is available in the user's language
- If not, translate it and save it

I could get it to work with my limited PHP knowledge, this is the code I tried:

$lang = $user->language;
$page->of(false);
$local_headline = $page->headline->getLanguageValue($lang);
if (!$local_headline) {
  $fluency = $modules->get('Fluency');
  $translate = $fluency->translate('en', $page->headline->getLanguageValue($lang), $lang->name);
  echo $translate;
  $page->headline = $translate;
  $page->save("headline");
}
$page->of;

The error I'm getting is:
Undefined variable: message in /modules/Fluency/engines/DeepL.class.php on line 172

So I'm working on a new release and I just found this the other day myself. To fix this right away, change the following on line 172:

<?php

// From:
wire('log')->save(self::ERROR_LOG, $message);

// To:
wire('log')->save(self::ERROR_LOG, $output['message']);

This line means that there was a problem with DeepL. Either it had trouble connecting or DeepL returned an error when you tried to translate. In the ProcessWire admin take a look at the Fluency log, I think it may be named "deeplwire-api". It should contain the error to help you troubleshoot.

  • Like 1
Link to comment
Share on other sites

  • FireWire changed the title to Fluency - The complete translation enhancement suite for ProcessWire

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...