Jump to content

Fluency - The complete translation enhancement suite for ProcessWire


FireWire

Recommended Posts

Thank you @FireWire, after some wrestling I got it working. My issue was that I assumed that the returned translation is a simple string while it's not.

For anyone interested, this is the working function I put together. It returns the translated field value or translates a multi-language field (headline in this case) on demand, if it's not yet translated.

You can call it simply <?= translate($page,'headline'); ?>. It's saved and displayed right away.
This way it can also be used in a foreach loop where you want to display a field from a different page.

Please let me know if something could be improved or simplified, I'm not a PHP guru.
Do you think it will have a toll on performance for already translated fields?

/* Translate a field if it's not available in current language
 *
 * @param object $page
 * @param string $field
 * @return string
 *
 */
function translate($page,$field) {
	// If field is empty there's nothing to be translated
	if (!$page->$field) return;
	// Get current language setting
	$lang = wire('user')->language;
	$page->of(false);
	// Check if the field is already translated
	$local_value = $page->$field->getLanguageValue($lang);
	if (!$local_value) {
	  $fluency = wire('modules')->get('Fluency');
	  // If not, translate it from default language
	  $translate = $fluency->translate('en', $page->$field, $lang->language_code);
	  // Get the translated string from the response object
	  $translated = $translate->data->translations[0]->text;
	  if ($translated) {
	  	// Save the translated value back to the field
	  	$page->$field = $translated;
	  	$page->save($field);
		// Set return value
	  	$local_value = $translated;
	  } else {
		// If translation fails and returns empty string
		// We use the default language
		$local_value = $page->$field;
	  }
	}
	$page->of;
	return $local_value;
}

There's still the issue of updated content in the original language but I'm not sure how to deal with that.

Link to comment
Share on other sites

Translating only for missing content should be good for performance. I do think that there are some items to consider.

  • If this is used in a template when the page loads and caching is used then this function isn't guaranteed to execute since a pre-rendered HTML document would be returned to the browser. Caching is a good idea for performance so this would create a situation where you can't use caching and that would be a performance hit.
  • If the content has been changed but you're only checking for the existence of translated text then it wouldn't re-translate. I have a solution for this but it would take a little extra code (detailed below)
  • There is a possibility that using the function you wrote could mean additional calls to the database. Someone with a little more knowledge of the ProcessWire core could correct me if I'm wrong. If that's the case then there could be a performance hit that is dependent on how performant your database setup is. Performance difference would depend on how performant your DB and DB connection is.
  • If you are running this loop on page load then the performance hit would really come from the delay in response from DeepL. Translation can take a couple of seconds in some cases and that will slow your page load time down a lot. This would only happen as long as something needs to be translated. If not then it will skip over the field and the page will load.

As for the translation return value- the module returns a passthrough payload directly from the DeepL API (I didn't develop the return data structure). This is good because it is predictable and unchanged from DeepL documentation, and it makes sense when you consider the ability to translate multiple separate texts at once. Take some time to review the README.md file in the Fluency module directory, it has documentation of the return data structure and details on using the module directly. I'll make a note to let module users know that information is there for review.

Solution for tracking changed content:

One way to verify content is to use hashing and WireCache. I am developing the next version of Fluency that will have a solution for this but in the meantime here is a modified solution that may fit your use case:

<?php

/**
 * Analyzes the content in a field determines if it has changed since the last time it was checked
 * @param  Page      $thisPage  Page containing field to check
 * @param  string    $fieldName Field object to check content for
 * @param  string    $lang      Name of language to check content for default is PW's default language
 * @return bool|null            Bool for content change, null if field doesn't exist on page
 */
function fieldChangedSinceCheck(Page $thisPage, string $fieldName, string $lang = 'default'): ?bool {
  if (!$thisPage->hasField($fieldName)) {
    return null;
  }

  $thisPage->of(false);
  $pageField = $thisPage->fields($fieldName);
  $isMultilanguageField = $pageField->type instanceof FieldtypeLanguageInterface;

  // Handle multi-language field
  if ($isMultilanguageField) {
    // Get the language, content in that language, and create a unique tracking ID
    $language = wire('languages')->get($lang);
    $current_field_content = $thisPage->$pageField->getLanguageValue($language);
    $key = "{$thisPage->id}|{$pageField->id}|{$language->id}";
  }

  // Handle non multi-language data
  if (!$isMultilanguageField) {
    $current_field_content = $thisPage->$fieldName;
    $key = "{$thisPage->id}|{$pageField->id}";
  }

  // Create a unique hash for the current content in this field in this language on this page
  $current_field_content_hash = hash_hmac('sha256', $current_field_content, $key);

  // Search WireCache for a previously stored content hash under this key if it exists, otherwise null
  $cached_field_content_hash = wire('cache')->getFor('field_content_tracking', $key);

  $contentHasChanged = false;

  // Compare the hash we created for the current content and compare it with the hash previously stored
  // If they do not match either it does not exist, or the content has been changed since it was last
  // analyzed
  if ($current_field_content_hash !== $cached_field_content_hash) {
    // Store the current content hash which will be used later to compare if content has changed
    wire('cache')->saveFor('field_content_tracking', $key, $current_field_content_hash);

    $contentHasChanged = true;
  }

  return $contentHasChanged;
}

There is a caveat, this solution will only tell you if it has updated since the last time it checked. So if a field was changed and you check the function will return true. If you check it again it will return false because it only tracks if it has changed since the last time it checked. I think this will still work for your use case as long as you act on it when it returns true. It works with multilanguage fields, regular fields, any language, and returns null if you try to check a value for a field that isn't on the page. Hope it helps!

Link to comment
Share on other sites

Thank you for the detailed answer, it's very educational. I was aware of some of the considerations but I didn't think about cache, for example.
I understand that the DeepL service take time, especially with a 5000 word document. ?
I did go through the readme multiple times before.
Great module and thanks again for the brilliant support here.

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...
6 hours ago, ngrmm said:

@FireWire thanks for the module!
Is there a way to force regular mode for CKEditorfields inside tables and use fluency? Or are they always in inline-mode, no matter what setting are set?

I haven't experienced that. I don't often use tables and can't remember if I've seen that.  Fluency wouldn't be able to change how a field is rendered. 

  • Like 1
Link to comment
Share on other sites

1 hour ago, FireWire said:

I haven't experienced that. I don't often use tables and can't remember if I've seen that.  Fluency wouldn't be able to change how a field is rendered. 

Looks like it's not possible. It says:

• settingsField: Specify a PW field that uses CKEditor to use for the settings of this column. Note that inline mode is always used, regardless of field settings.
• …

 

Link to comment
Share on other sites

5 hours ago, ngrmm said:

Looks like it's not possible. It says:

• settingsField: Specify a PW field that uses CKEditor to use for the settings of this column. Note that inline mode is always used, regardless of field settings.
• …

 

Dangit. Sorry to hear that. The inline CKEditor thing is on my list but won't be added until the next version which I'm working on right now. The way that field renders is much different from other fields. I'll be sure to add that to the priority list to see what can be done.

Link to comment
Share on other sites

  • 1 year later...

@FireWire I imagine that TinyMCE is a whole different beast and would require a ton of refactoring, but I was wondering whether you have considered working on a version that would support Processwire’s new default editor. Thanks for your work!

  • Like 1
Link to comment
Share on other sites

On 5/13/2023 at 3:23 PM, jacmaes said:

@FireWire I imagine that TinyMCE is a whole different beast and would require a ton of refactoring, but I was wondering whether you have considered working on a version that would support Processwire’s new default editor. Thanks for your work!

I've been following the news on the new editor and I'll be adding that to the next version of the module. The module is already getting refactored so I'll be able to plan for this much more easily.

I'll work on posting some updates here with some details on what's planned!

  • Like 5
Link to comment
Share on other sites

  • 3 weeks later...

Hello all!

I've compiled a list of features that Fluency will have on it's next release and currently under development. There are a lot of new features and, as mentioned, it's being completely rewritten. I want to share some notable features that I think will be some great additions. IMHO, I believe that this puts Fluency in a first-rate position to make ProcessWire easier and more powerful for multi-language sites compared to other CMS/CMF platforms. If you've tried to use translation modules/plug-ins for other platforms I think you'll agree.

As you can imagine, the feature expansion makes the module very powerful but it also means a lot of extra work. There will be an upgraded version available named (unsurprisingly) FluencyPro. Before I get into that, my commitment is to make the non-pro version the real-deal when it comes to quality and features. No features will be taken away from the core Fluency module and moved to the premium module. As you'll see below, the majority of new features will be available in the Fluency core version. Every feature in FluencyPro is new and complements the Fluency module that is and will always be free. I also want to make the Pro version very reasonably priced so it can remain within reach for as many people as possible and an easy sell to clients. The price will help offset the time and effort it takes and the support is greatly appreciated. More details to follow on that later.

I chose the new features based on feedback from the community as well as my usage for sites I've built.

Here is a list of new features that are coming in the next version:

Fluency (core)

  • Continuity - All existing features will still be available
  • Localization - All Fluency admin UI elements can be translated to all languages present in ProcessWire. Includes the translation trigger buttons on each field, the global translation tool in the menu, etc.
  • Error Handling - Will indicate things like the DeepL service not being available, usage limit reached. All errors will be translatable.
  • Improved Module Config - Cleaner and more organized module config screen
  • Inline Fields - Support for inline fields
  • TinyMCE - Support for the new rich text editor
  • CKEditor - Continued support for CKEditor to keep the module backwards compatible with ProcessWire sites that don't/can't use TinyMCE
  • Per-language change indication - When content is changed in a field, the corresponding language tab will indicate that the content has been changed. This makes it easy to see where content should be updated in other languages.
  • Translation Caching - Translations will be cached so that additional requests for the same content will not require additional DeepL API calls. This can help keep monthly DeepL API usage lower where possible and make repeated translations lighting fast. Cache can be manually cleared in the module config screen
  • Logging - Improved
  • Remains free - Free forever and will be open-sourced

FluencyPro

  • Multi-Language - Translate any content to any language for a field.
  • Multi-Language - Translate any content from any language for a field.
  • One Click Translate All - Any language to every other language for a field.  This makes using a wider array of languages trivial when editing pages
  • Markup Companion Module - Optional FluencyMarkup module provides individual easy-to-use methods for markup output to the front-end. This makes Fluency a complete translation solution out of the box. Features:
    • Render all languages as prebuilt `<a>` links to navigate between page languages.
    • Render a self-contained prebuilt `<select>` element with one click switching between languages on the front end while needing no additional JS required in your code. Inline JS is optional for those who prefer to implement their own.
    • Render all alternate language `<link rel="alternate" hreflang="{ISO code}" href="{alt language URL}">` `<head>` tags to indicate that the page has additional versions in other languages. Great for SEO and adhering to HTML standards.
    • Output the current language ISO code. Useful for turning `<html>` into `<html lang={ISO code}>` in keeping with HTML best practices.
    • All render methods are hookable for additional customization by developers

Notable overall code improvements:

  • Written using PHP 8.0 (required for use)
  • JavaScript rewritten in ES6 to make use of newer language features, is transpiled to ES5 to maintain browser compatibility. Transpiling is pre-configured and included with the module.
  • Modular per-inputfield JavaScript so that adding new field types and updating existing ones in the future is faster and easier. Standardized composition so interfacing with fields within code is uniform and predictable.
  • Server-side module code is being rewritten with the future potential to add additional "translation engines". While there won't be additional services available now, there will be a more standardized interface to make adding others easier. Both versions of Fluency will have this feature and can benefit from new translation services other than DeepL. This won't be 100% ready on release, but it is being kept in mind now.
  • Future translation engines will have access to a uniform interface to use the Fluency caching feature with no additional overhead during development.
  • Improved RESTful style API within the admin which lets other modules or PW customizations implement separate translation features using AJAX requests
  • Leverages ProcessWire's built in JavaScript config object (as opposed to a separate API request on page admin page load) to speed up UI initialization
  • .prettierrc and .editorconfig files to make contributing easier

Thanks everyone for your patience, really excited for the new features! Cheers!

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

This is great to read! And I think it’s only fair to think about ways to make it sustainable for you.

I’m not 100% sure I would need the Pro version but just for the sake of supporting your great module I wouldn’t mind paying that extra. This is a thing I really (reeeeeally) like with Ryan’s Pro modules model: provide an excellent base and sell this nice extra bit (that can be big) to allow to support the work.

Now, I’m close to start working on a client’s website where I will be using your module (of course) and I have some questions:

  • do you happen to have an ETA for this update?
  • will the update process be smooth between the current version and the new one? I assume it will be but I prefer asking.
  • finally: would you recommend to wait to get TinyMCE support?

Thanks again for the great work and looking forward for the release.

  • Like 2
Link to comment
Share on other sites

8 hours ago, monollonom said:

This is great to read! And I think it’s only fair to think about ways to make it sustainable for you.

I’m not 100% sure I would need the Pro version but just for the sake of supporting your great module I wouldn’t mind paying that extra. This is a thing I really (reeeeeally) like with Ryan’s Pro modules model: provide an excellent base and sell this nice extra bit (that can be big) to allow to support the work.

Now, I’m close to start working on a client’s website where I will be using your module (of course) and I have some questions:

  • do you happen to have an ETA for this update?
  • will the update process be smooth between the current version and the new one? I assume it will be but I prefer asking.
  • finally: would you recommend to wait to get TinyMCE support?

Thanks again for the great work and looking forward for the release.

I'm glad you asked this!

This should be pretty much a drop in replacement. The only thing you'd have to do to upgrade to the new version would be setting the language associations again and transfer any settings (like global excluded strings and API key) in the module config. Upgrading later will not cause any loss of website content and the work for developers should be minimal. The new features are implemented behind the scenes, so you just get more cool stuff 😎.

ProcessWire makes it possible to change editors between TinyMCE and CKEditor without re-creating the field, so using CKEditor editor now and then switching to TinyMCE later shouldn't cause any headaches. It really should be as easy of a transition as you can get with how well TinyMCE is concurrently being implemented (props to @ryan). As for the module, Fluency doesn't care what field/editor you use or if it's changed at any time because fieldtypes are detected and initialized by JS at runtime when the UI loads, not on the back end.

So good news- I don't believe that there is anything that keeps you from using Fluency now and upgrading later.

I've been working regularly on the module lately, my goal is this month or next. I think a wildcard will be testing but I'll be requesting help from the community here when it's time. I want this version to be the one that breaks out of alpha.

Many thanks and I'll report back here when I have updates.

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

9 hours ago, jacmaes said:

This is indeed an exciting update with many improvements and clearly a ton of planning. I would also support you with a Pro license as @monollonom said. 

The planning is 100% with an eye on the future. Thank you for the kind words and support!

Link to comment
Share on other sites

  • 2 weeks later...

 Thanks to @teppo for the ProcessWire Weekly shoutout! I wanted to share some updates to show I haven't been a lazyass some more detail and information since my last update post.

Caching is optional and can be cleared. Translations are persisted for 1 month which helps even out month-to-month API usage, but also expires so if DeepL improves their translation then you still get the latest and greatest. I haven't formally timed it but cached translations feel near instantaneous.

cache_config.png.e4f017b6323838632a877eb0f1e8e06f.png

Modified content? If the content of a field has changed since the page edit screen was loaded- then the tab text is italicized and an accent is added. This tracks changes whether you typed the text, or if you used the translator to change the content. It's stateful so if you return the content to the original value, the accent is removed to indicate that the content has not changed.

Oh, and this is tracked independently for each field, and separately for each language. So it is now much easier to see if there are fields that weren't translated. Heck, it even helps users make sure they didn't miss anything anywhere before they hit Save.

change_tracking_per_language.png.78cc1f2d5ba037577b430e0c43ec6379.png

Table fields are now supported. I forgot to mention that before. Fluency has been tested with all ProFields and is 100% compatible.

table.thumb.png.d6bdbfbd826cad3ccdc4a94fcb714c05.png

TinyMCE is ready to go and, as promised, CKEditor regular and inline are also supported

tiny_mce.png.9e2edce3dfd79d108c12ede44f83cd54.png

Error handling! Fluency is aware of all errors that are possible to be received back from DeepL. It's also smart enough to know if the DeepL service is unavailable or if you lost connection to ProcessWire (what wifi?). This helps make it very clear where the error happened, which may save you some headaches during development (and maybe emails from your clients/users later). In my case DeepL rejects requests when I'm on a VPN even if my internet is workin' alright.

error_service_unavailable.png.2a9bae54ee0e80039d5ba11e633848a3.png

error_unable_to_connect.png.b1b1ded9e63509ee8e97918e8f8d7c67.png

Localization is here. Every single aspect of Fluency is translatable using one central file in the admin language configuration. That's it. No chasing different files in the module to translate things. English is the default language in these pics, but it also shows the proper language if your default isn't.

localization_1.png.3efe29feddd91d67faeddb2e8d582ff2.png

localization_2.png.57834d9535a40b8d21ef60b2f0c0680d.png

Achtung! Even the errors speak your language. I got you, international friends.

localization_3.png.95feb8db586d6509aca97a8a56d258c7.png

For the nerds... One field, one file, full documentation. Each field adheres to standardized public interface methods so they are modular and completely independent of the rest of the codebase. If the old code was structured like this TinyMCE would have been ready the day after it was announced by Ryan. Not every inputfield needs its own module because some fields just use others- a repeater containing a textarea still just counts as a textarea. Less module updates, more translating!

field_files.png.7e63a7bc3a884c6400bbfb2adb6276e2.png

All of these are core Fluency features. I'm prioritizing this over any work on a Pro module to get this out for testing and into everyone's hands sooner.

Still work to be done, already 3x more code than the last version, but we're bringing the 🔥

More updates to come!

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

  • 3 months later...

Well here's a big announcement. The full rewrite is done.

I bet you thought I forgot about this project, but nothing could be further from the truth... This is a complete rewrite of Fluency and it has a lot of new features- including a big one I said wouldn't be ready... it's now possible to use other translation services besides DeepL. Currently only two are available, DeepL and Google Cloud Translation. However- Fluency now includes a complete framework for creating "Translation Engines" that power fluency. I'm working on documentation and contributions in the future are welcome!

There are a lot of features that have been added. Some I mentioned above, but they're here too.

  • Ability to add new translation API services and a framework for developing them
  • Language tabs now have indicators to show where content has been changed since page load. This makes it easier to see if some languages have not been converted
  • Per-engine configurations. The Fluency module config page will dynamically show you the configurations that are needed for each engine.
  • Translation engines retain their own configurations. It is possible to switch between engines with very little work.
  • Full support for all ProcessWire fields, including TinyMCE. Both TinyMCE and CKEditor inline modes are now supported as well
  • Polite and informative error handling
  • Full UI translation for all Fluency components. Errors, buttons, labels, everything in Fluency itself can be translated and therefore customized.
  • Full caching for translations and language lists. Caching can be cleared on demand.
  • DeepL now has full support for translation features, including formality
  • The module config is much nicer
  • Meta tags for alternate languages can be rendered for the <head> element
  • A language select dropdown can be rendered that reloads the page in a selected language
  • You can easily get the language ISO code as well
  • There's more, I'm probably forgetting some stuff. Check the module code.
  • If you want to see what an overengineered ProcessWire module looks like, check the code.

Check the methods in Fluency.module.php. Fluency is now globally accessible using the $fluency variable if anyone uses it. The admin REST API is completely documented as well. I'll be following up with more documentation on building Translation Engines, but it's already started and located in the module's subdirectories.

Oh- and all documentation within the module is fully formatted and compatible with the outstanding ProDevTools module API Explorer. I've come to love that tool so I made my module work with it as well.

I put all of the markup features I mentioned adding in a Pro module into this one. I'm not going to build a Pro module, all future features are going into this one. So it's all free now and forever.

https://github.com/SkyLundy/Fluency

Let me know what you think and about any bugs found. Also interested in hearing what other translation services you are interested in, and if there's any interest in someone helping out with building new Translation Engines!

  • Like 7
  • Thanks 5
Link to comment
Share on other sites

  • 3 weeks later...

Hey @FireWire, thanks for the fabulous update! I have a question regarding DeepL...

I don't understand their pricing! For my website I think I'm fine with my free developer API account. I've translated several blocks of content and I've used only 1% of my limit. That's really great and has saved me so much time!

That feature would be great for so many multilingual websites so I'm thinking about how I could sell that to clients. What plan would I need then? Would I let them use my developer key? Or would they need to register their own account? They would not be allowed to use the free dev plan I guess, so what would be the correct plan?

There's only one for a single person starting from 9€ per Month, which is not so cheap. Especially for websites where you don't have lots of changes...

Thx for your help (or anybody else who has an answer)!

Link to comment
Share on other sites

On 10/5/2023 at 10:09 AM, bernhard said:

Would I let them use my developer key? Or would they need to register their own account?

Clients should always have their own accounts! If a features that a client wants or needs that need a 3rd party service, I present the information to the client, explain the pricing, and let them know that the account will be a service that they subscribe to. I like to emphasize that this means that they have ownership of the service and don't have someone in the middle (like me) charging a premium as a reseller.

An example besides DeepL is a service called Smarty, which is an API to work with addresses. I am doing work with a client's CRM and explained that their address data isn't high quality enough to complete the work they need. I told them there's a free 30 day trial, and after that it's $54/mo. It sounds steep, but the client understood that it was an important necessity. It's a cost of doing business for them, just like DeepL may be.

On 10/5/2023 at 10:09 AM, bernhard said:

what would be the correct plan?

There are two sets of pricing for DeepL, the price to use their application, and the price to use their API. There are 2 separate pages for subscription plans, and on the "Plans and pricing" page it has both subscription types. It can be confusing due to how they have it presented. Here's where they have that hidden:

deepl_pricing.thumb.jpg.2295db3eba2df46d96506a55dd564511.jpg

I looked at the pricing plans and I don't see anything that would prevent a client from using the Free plan, unless 500,000 characters isn't enough. Then it would be €5.49 to sign up for the Pro plan, and then €20.00 for an additional 1,000,000 characters. So 1.5 million characters for €25.49. If it really came to that I would think that in most cases it would be possible to sign up for one month of Pro to translate the initial large amount of content, and then downgrade to the Free plan with 500,000 characters- unless they're publishing a ton of content per month!

In Fluency you can switch between Free and Pro accounts without any issues or additional configurations needing to be made. Hope that helps, but if not let me know.

Edited by FireWire
Fixed DeepL pricing, looked like I couldn't do maths.
  • Like 4
Link to comment
Share on other sites

  • 2 weeks later...

@FireWire I'm building my first ProcessWire website, in large part because WordPress has been such a poor solution for clients who need multilingual sites. Your module has the potential to make ProcessWire amazing. Thank you! I have a couple questions:

  1. Will this be added to the ProcessWire modules directory at some point to make it easier to apply updates?
  2. I've added a DeepL developer API key, which seems to be working well enough to tell me my usage information from withing ProcessWire. I've tested my key using curl and it has returned translations. However I cannot get any translations to actually return to the site (see screenshot below). This does not appear to be browser specific. What suggestion do you have to debug this problem?

image.thumb.png.8a5d3c2df96ed10407b8212c8169e3ba.png

Link to comment
Share on other sites

I've had a similar issue and for me it was the problem that the endpoint was not reachable. The reason was that I moved the fluency page in the admin from the top level down into the setup tab.

You can try to inspect the network tab of your devtools and see what response you get from the fluency api request. It should be JSON - for me it was HTML.

I've talked to @FireWire about changing his implementation to url hooks to prevent this issue. Maybe it's something similar for you. Maybe you moved the page as well or maybe you have any other redirects going on from some hooks?

  • Like 1
Link to comment
Share on other sites

PS

4 hours ago, ryangorley said:

I'm building my first ProcessWire website, in large part because WordPress has been such a poor solution for clients who need multilingual sites.

Maybe you can share more details about this here or in the pub? It's always good to know the competition and to know what problems client might face if they want to use WordPress...

PPS: I tried to edit my post but the forum software decided to create a new one, sorry 😄 

  • Like 1
Link to comment
Share on other sites

14 hours ago, ryangorley said:

@FireWire I'm building my first ProcessWire website, in large part because WordPress has been such a poor solution for clients who need multilingual sites. Your module has the potential to make ProcessWire amazing. Thank you! I have a couple questions:

  1. Will this be added to the ProcessWire modules directory at some point to make it easier to apply updates?
  2. I've added a DeepL developer API key, which seems to be working well enough to tell me my usage information from withing ProcessWire. I've tested my key using curl and it has returned translations. However I cannot get any translations to actually return to the site (see screenshot below). This does not appear to be browser specific. What suggestion do you have to debug this problem?

image.thumb.png.8a5d3c2df96ed10407b8212c8169e3ba.png

Welcome to ProcessWire! Hope your experience has been great thus far (well, aside from this error you're seeing) and thank you for the kind words.

1. Absolutely will be adding it to the modules directory. I'd like to get a couple of tweaks in and iron out any bugs that may pop up, I have done as much testing as I can on my own and I need to make sure that "it works for me" means "it works for everyone" haha. @bernhard had a great suggestion for using hooks. As soon as it's had a little bit of usage I think it will be ready for the modules directory, so your feedback and bug reports are very helpful.

2. Translation engine requests are logged, so check the 'fluency-engine' log. That should help figure more out. If that isn't helpful then try using the network tab under your browser development tools, try translating something, then check the JSON response. Another question- does the translation tool accessed by the menu at the top of the page work?

I too have had some secondhand experience with the challenges of adding multi-language capabilities to WordPress. My partner manages a WP site for the company they works for and had to try several plugins, some worked partially, all were difficult to use. Fluency was designed to be better than anything WP has available and those problems guided my work.

9 hours ago, bernhard said:

PS

Maybe you can share more details about this here or in the pub? It's always good to know the competition and to know what problems client might face if they want to use WordPress...

PPS: I tried to edit my post but the forum software decided to create a new one, sorry 😄 

Feel free to share your story over in this forum post celebrating WordPress.

  • Like 2
Link to comment
Share on other sites

@FireWire I get the same error translating both pages and via the menu. Nothing is reported in the `fluency-engine.txt` log file, however I am getting the following error in the `errors.txt` log each time I attempt a translation:

2023-10-16 14:30:46	freehive	https://latticework.freehive.net/panel/fluency/api/translation/	Fatal Error:  Uncaught TypeError: str_replace(): Argument #1 ($search) must be of type array|string, bool given in /home/latticework/webapps/latticework-pw/site/modules/Fluency/app/Engines/DeepL/DeepLEngine.php:313 

Stack trace: 
#0 /home/latticework/webapps/latticework-pw/site/modules/Fluency/app/Engines/DeepL/DeepLEngine.php(313): str_replace() 
#1 [internal function]: Fluency\Engines\DeepL\DeepLEngine->Fluency\Engines\DeepL\{closure}() 
#2 /home/latticework/webapps/latticework-pw/site/modules/Fluency/app/Engines/DeepL/DeepLEngine.php(305): array_reduce() 
#3 [internal function]: Fluency\Engines\DeepL\DeepLEngine->Fluency\Engines\DeepL\{closure}() 
#4 /home/latticework/webapps/latticework-pw/site/modules/Fluency/app/Engines/DeepL/DeepLEngine.php(304): array_map() 
#5 /home/latticework/webapps/latticework-pw/site/modules/Fluency/app/Engines/DeepL/DeepLEngine.php(71): Fluency\Engines\DeepL\DeepLEngine->addIgnoredTags() 
#6 /home/latticework/webapps/latticework-pw/site/modules/Fluency/Fluency.module.php(791): Fluency\Engines\DeepL\DeepLEngine->translate() 
#7 /home/latticework/webapps/latticework-pw/site/modules/Fluency/Fluency.module.php(974): ProcessWire\Fluency->translate() 
#8 /home/latticework/webapps/latticework-pw/site/modules/Fluency/Fluency.module.php(950): ProcessWire\Fluency->apiTranslateEndpoint() 
#9 /home/latticework/webapps/latticework-pw/wire/core/ProcessController.php(361): ProcessWire\Fluency->executeApi() 
#10 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(413): ProcessWire\ProcessController->___execute() 
#11 /home/latticework/webapps/latticework-pw/wire/core/WireHooks.php(968): ProcessWire\Wire->_callMethod() 
#12 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks() 
#13 /home/latticework/webapps/latticework-pw/wire/core/admin.php(160): ProcessWire\Wire->__call() 
#14 /home/latticework/webapps/latticework-pw/site/templates/admin.php(18): require('...') 
#15 /home/latticework/webapps/latticework-pw/wire/core/TemplateFile.php(328): require('...') 
#16 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(413): ProcessWire\TemplateFile->___render() 
#17 /home/latticework/webapps/latticework-pw/wire/core/WireHooks.php(968): ProcessWire\Wire->_callMethod() 
#18 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks() 
#19 /home/latticework/webapps/latticework-pw/wire/modules/PageRender.module(574): ProcessWire\Wire->__call() 
#20 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(416): ProcessWire\PageRender->___renderPage() 
#21 /home/latticework/webapps/latticework-pw/wire/core/WireHooks.php(968): ProcessWire\Wire->_callMethod() 
#22 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks() 
#23 /home/latticework/webapps/latticework-pw/wire/core/WireHooks.php(1094): ProcessWire\Wire->__call() 
#24 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks() 
#25 /home/latticework/webapps/latticework-pw/wire/modules/Process/ProcessPageView.module(184): ProcessWire\Wire->__call() 
#26 /home/latticework/webapps/latticework-pw/wire/modules/Process/ProcessPageView.module(114): ProcessWire\ProcessPageView->renderPage() 
#27 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(416): ProcessWire\ProcessPageView->___execute() 
#28 /home/latticework/webapps/latticework-pw/wire/core/WireHooks.php(968): ProcessWire\Wire->_callMethod() 
#29 /home/latticework/webapps/latticework-pw/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks() 
#30 /home/latticework/webapps/latticework-pw/index.php(55): ProcessWire\Wire->__call() 
#31 {main}   thrown (line 313 of /home/latticework/webapps/latticework-pw/site/modules/Fluency/app/Engines/DeepL/DeepLEngine.php)

I rolled the site back to PHP 8.1 in case this was a PHP version specific issue, but it didn't fix it. Hopefully this error helps. Thanks for the help!

Link to comment
Share on other sites

@ryangorley This is helpful and I'll try to replicate this. Have you added anything into the "Global Non-Translated Strings" field on the module config page? What are your settings for "Preserve Formatting" and "Formality"?

I was able to replicate this by adding some excluded strings in the module config, let me know if this happened without your having added any.

Fluency is compatible up through 8.2, I held off on using some 8.2 features to keep it compatible with more installs and the rest of the code is up to date, this is an isolated bug. So go with 8.2!

Edited by FireWire
Found the problem.
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...