Jump to content

Search the Community

Showing results for 'DeepL'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk

Product Groups

  • Form Builder
  • ProFields
  • ProCache
  • ProMailer
  • Login Register Pro
  • ProDrafts
  • ListerPro
  • ProDevTools
  • Likes
  • Custom Development

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

  1. Hello community! I want to share a new module I've been working on that I think could be a big boost for multi-language ProcessWire sites. Fluency is available in the ProcessWire Modules Directory, via Composer, and on Github Some background: I was looking for a way for our company website to be efficiently translated as working with human translators was pretty laborious and a lack of updating content created a divergence between languages. I, and several other devs here, have talked about translation integrations and the high quality services now available. Inspired by what is possible with ProcessWire, I built Fluency, a third-party translation service integration for ProcessWire. With Fluency you can: Translate any plain textarea or text input Translate any TinyMCE or CKEditor (inline, or regular) Translate page names/URLs Translate in-template translation function wrapped strings Translate modules, both core and add-ons Installation and usage is completely plug and play. Whether you're building a new multi-language site, need to update a site to multi-language, or simply want to stop manually translating a site and make any language a one-click deal, it could not be easier to do it. Fluency works by having you match the languages configured in ProcessWire to those offered by the third party translation service you choose. Currently Fluency works with DeepL and Google Cloud Translation. Module Features Translate any multilanguage field while editing any page. Translate fields in Repeater, Repeater Matrix, Table, Fieldset Page, Image descriptions, etc. Translate any file that added in the ProcessWire language pages. It's possible to translate the entire ProcessWire core in ~20 minutes Provide intuitive translation features that your clients and end-users can actually use. Fluency is designed for real-world use by individuals of all skill levels with little to no training. Its ease-of-use helps encourage users to adopt a multilanguage workflow. Start for free, use for free. Translation services supported by Fluency offer generous free tiers that can support regular usage levels. Fluency is, and will always be, free and open source. Use more than one Translation Engine. You may configure Fluency to use either DeepL, Google Cloud Translation, or both by switching between them as desired. AI powered translations that rival humans. DeepL provides the highest levels of accuracy in translation of any service available. Fluency has been used in many production sites around the world and in commercial applications where accuracy matters. Deliver impressive battle-tested translation features your clients can count on. Disable translation for individual fields. Disable translation for multilanguage fields where values aren't candidates for translation such as phone numbers or email addresses Configure translation caching. Caching can be enabled globally so that the same content translated more than once anywhere in ProcessWire doesn't count against your API usage and provides lightning fast responses. Set globally ignored words and text. Configure Fluency to add exclusionary indicators during translation so that specific words or phrases remain untranslated. This works either for specific strings alone, or present in other content while remaining grammatically correct in translation. Choose how translation is handled for fields. Configure Fluency to have buttons for either "Translate from {default language}" on each tab, or "Translate To All Languages" to populate every language for a field from any language to any language you have configured. No language limits. Configure as few or as many languages as you need. 2, 5, 10, 20 language website? Absolutely possible. If the translation service you choose offers a language, you can use it in ProcessWire. When new languages are introduced by third parties, they're ready to use in Fluency. Visually see what fields and language tabs have modified content. Fluency adds an visual indication to each field language tab to indicate which has different content than when opening the edit page. This helps ensure that content updated in one language should be updated in other languages to prevent content divergence between languages. Render language meta tags and ISO codes. Output alt language meta tags, add the current language's ISO code to your <html lang=""> attribute to your templates that are automatically generated from accurate data from the third party translation service. Build a standards-compliant multi-language SEO ready page in seconds with no additional configuration. Render language select elements. - Fluency can generate an unordered list of language links to switch between languages when viewing your pages. You can also embed a <select> element with JS baked in to switch between languages when viewing your pages. Render it without JS to use your own. Manage feature access for users. Fluency provides a permission that can be assigned to user roles for managing who can translate content. Track your translation account usage. View your current API usage, API account limit, and remaining allotment to keep an eye on and manage usage. (Currently only offered by DeepL) Use the global translation tool. Fluency provides translation on each field according to the languages you configure in ProcessWire. Use the global translation tool to translate any content to any language. Use Fluency from your templates and code. All translation features, usage statistics, cache control, and language data are accessible globally from the $fluency object. Perform any operation and get data for any language programmatically wherever you need it. Build custom AJAX powered admin translation features for yourself. Fluency provides a full RESTful API within the ProcessWire admin to allow developers to add new features for ProcessWire applications powered by the same API that Fluency uses. Robust plain-language documentation that helps you get up to speed fast. Fluency is extremely easy to use but also includes extensive documentation for all features both within the admin and for the Fluency programming API via the README.md document. The module code itself is also fully annotated for use with the ProDevTools API explorer. Is and will always be data safe. Adding, upgrading, or removing Fluency does not modify or remove your content. ProcessWire handles your data, Fluency sticks to translating. Full module localization. Translate Fluency itself to any language. All buttons, messages, and UI elements for Fluency will be presented in any language you choose for the ProcessWire admin. Built for expansion. Fluency provides translation services as modular "Translation Engines" with a full framework codebase to make adding new translation services easier and more reliable. Contributions for new translation services are welcome. Fluency is designed and built to provide everything you need to handle incredibly accurate translations and robust tools that make creating and managing multi-language sites a breeze. Built through research on translation plugins from around the web, it's the easiest and most friendly translation implementation for both end users and developers on any CMS/CMF anywhere. Fluency complements the built-in first class language features of ProcessWire. Fluency continues to be improved with great suggestions from the community and real-world use in production applications. Big thanks to everyone who has helped make Fluency better. Contributions, suggestions, and bug reports welcome! Please note that the browser plugin for Grammarly conflicts with Fluency (as it does with many web applications). To address this issue it is recommended that you disable Grammarly when using Fluency, or open the admin to edit pages in a private window where Grammarly may not be loaded. This is a long-standing issue in the larger web development community and creating a workaround may not be possible. If you have insight as to how this may be solved please visit the Github page and file a bugfix ticket. Enhancements Translate All Fields On A Page Compatibility with newest rewrite of module is in progress... An exciting companion module has been written by @robert which extends the functionality of Fluency to translate all fields on a page at once. The module has several useful features that can make Fluency even more useful and can come in handy for translating existing content more quickly. I recommend reading his comments for details on how it works and input on best practices later in this thread. Get the module at the Github repo: https://github.com/robertweiss/ProcessTranslatePage Requirements: ProcessWire 3.0+ UIKit Admin Theme That's Fluency in a nutshell. The Module Is Free This is my first real module and I want to give it back to the community as thanks. This is the best CMS I've worked with (thank you Ryan & contributors) and a great community (thank you dear reader). DeepL Developer Accounts In addition to paid Pro Developer accounts, DeepL now offers no-cost free accounts. All ProcessWire developers and users can use Fluency at no cost. Learn more about free and paid accounts by visiting the DeepL website. Sign up for a Developer account, get an API key, and start using Fluency. Download You can install Fluency by adding the module to your ProcessWire project using any of the following methods. Method 1: Within ProcessWire using 'Add Module From Directory' and the class name Fluency Method 2: Via Composer with composer require firewire/fluency Method 3: Download from the Github repository and unzip the contents into /site/modules/ Feedback File issues and feature requests here (your feedback and testing is greatly appreciated): https://github.com/SkyLundy/Fluency/issues Thank you! ¡Gracias! Ich danke Ihnen! Merci! Obrigado! Grazie! Dank u wel! Dziękuję! Спасибо! ありがとうございます! 谢谢你
  2. Maybe we can extend the site-wide search to include the body / description of modules as well, be it with less priority? This is an example of a use case: I knew a module exists that uses DeepL to translate site content, but when I searched for DeepL I got 0 results: https://processwire.com/search/?q=DeepL. However, DeepL gets mentioned 5 times in the body of this module page. It was only until I tried searching for terms like 'Translate' that I could find this module. Edit: there is another module that I missed and in my opinion should have popped up.
  3. @snck The purpose of the requests on the config page are to confirm that your API key works by making an API request to get the available languages. The only time that it will make 4 API calls on the config page is when you are first entering your API credentials. After you have entered valid credentials it will only make 2 API calls when you load the module config page. This hasn't ever been an issue before so I'm very curious why you are seeing a 429 but others haven't. Here's some additional details on why you are seeing 2 or 4 API calls for languages in Fluency when using DeepL: Fluency needs to know what languages a service allows you to translate from and what languages you can translate to. Google Cloud Translate will give you this information in 1 API call. DeepL requires you to make two API calls, one for source languages and one for target languages. Fluency is built with a modular architecture so that new translation services can be added easily. If you're interested you can compare DeepLEngine.php with GoogleCloudTranslationEngine.php. Each have the same methods that return the same data type but how it gets that data is entirely internal. To see what I mean about the 2 API calls vs 1 API call compare the getLanguages() method in each of those. 2 API calls is technically just one execution of the getLanguages() function. You should only see 4 API calls when: You first enter your API credentials and hit save You change translation engines You entered incorrect credentials and have to re-enter them After that it should only be 2 when using DeepL in Fluency. Back to your issue- 4 API calls shouldn't cause a 429. The DeepL team states that API calls should be limited to 50 requests per second. That comment is in an issue in their Node library, but the limits should still apply for all API usage. I just removed my credentials and re-added them without any issues. Are you seeing 4 API calls every time you load or save the module config page? I have to ask the obligatory security question- is there any chance that your credentials are being used by someone else or were compromised? I know that you said that you just created your API key today but you would have to be absolutely hammering the DeepL API to get a 429. I've never seen it during regular usage and it hasn't come up here in the forums by anyone who has been using the module for years. This is a tough issue to crack especially since it's happening for you but not me at the same time. Let me know if there's any additional info you can share.
  4. @snck That may be a gamble... I think I've seen some situations where DeepL responses aren't very descriptive beyond the HTTP code that they return which can be frustrating. Unfortunately when I test my API key (free) I'm getting translations successfully. In your case the only way to get "Translation rate limit exceeded" is if DeepL returns an HTTP 429 code so that is another message that Fluency is relaying to you from DeepL and not originating with anything in the module. Whether the HTTP 429 applies in your case, I don't know. You may want to check the API key type that you have and ensure that it is valid for making translation requests. If you would like to see what DeepL is responding with directly and you aren't afraid to dig into some code then you can dump the response at L252 in DeepLEngine.php. Because the translations are made via AJAX in ProcessWire, you'll have to use the developer tools in your browser to view the response after clicking the translate button for a field. If you're using Tracy then adding bd() is the best way to see the result in your browser. Sorry I can't be of more help, there have been some instances in this thread where people have had some hiccups with DeepL. It doesn't happen very often and when you find the cause/solution for your issue here it should be smooth sailing.
  5. That would be nice. To be honest, I never use forums or website search. By default, I just fire up Google. My usual suspects are /talk /blog /docs site:processwire.com/ deepl site:processwire.com/talk deepl site:processwire.com/blog languages site:processwire.com/docs $page
  6. Hmm I was about to test it, on the specific customer project, who had that problem and now I'm hit on the Problem in the plugin configuration screen. So Fluency will not more let me connect the languages from ProcessWire to the DeepL one, and so I can not test it. Sorry. If it helps, the TranslatePage (via DeepL) - Plugin on the other hand, has no problems with the same API-Key.
  7. Yeah, that's DeepL returning 429 as your error and nothing as the response body. I'm at a loss on how to diagnose that. Have you been able to translate content successfully in the past? Have you used up your allowable number of translated characters? This is going to have to be something on the DeepL side and I don't know if there's anything I can do to help out. Like I mentioned, I just translated using my API key and things are working alright.
  8. @FireWire Thanks! I had already checked that. I picked "Free" (which is correct) and inserted a valid API key that has never been used before. I only get the "Translation rate limit exceeded, please wait then try again" error (see below). The fluency-engine logs show the following message: Engine: DeepLEngine /Error: RATE_LIMIT_EXCEEDED /Message: No Message /Response: null Is there any other place where I could look for more verbose information? I tested the API key and made sure it is correct: curl -X POST 'https://api-free.deepl.com/v2/translate' -H 'Authorization: DeepL-Auth-Key [MY API KEY]' -d 'text=Hello%2C%20world!' -d 'target_lang=DE' {"translations":[{"detected_source_language":"EN","text":"Hallo, Welt!"}]}%
  9. @Tiberium I have another way to attack this so I'll put together another commit on that branch and let you know. Unfortunately adding an ability to manually assign languages like the TranslatePage module would be a heavier lift than you might think since there are more features that Fluency uses. It would require rewriting the module config page for DeepL. The true solution is to make sure that the module performs correctly for everyone and preserve the UI that people are familiar with. It wouldn't be a good move to require some people who are having difficulty with API calls to forego features that are available to others who aren't. So I want to get this right for everyone 👍 Hold tight, I'll come back with another test. Please expect that via private message so we can more easily converse without adding too many more posts to this thread. When the issue is solved I'll come back and post a new release.
  10. @Mike-it some steps: Double check that you've picked the correct "Free" or "Pro" subscription type on the module config page. This is an issue with a DeepL account, API key, or a Free/Pro setting. If you receive that error again, next to the "check credentials" there is a +2, click on the chevron-down and see what the additional message is that may be hidden. There is only one place in the module that can return that error message and it is based on the HTTP response status. So in that case, DeepL is indeed returning an HTTP 403 and Fluency is just relaying the information. The error message you're seeing is the "polite" message from Fluency. Any errors returned by a translation service are logged so there may be a more specific message in the fluency-engine log if DeepL provided one.
  11. @FireWire No, never used Fluency or the DeepL API before. The account has been created today, the key is fresh and I could successfully use it with curl from the shell without problems. I do not really understand the goal of the requests that are made on the settings page. As I get status 200 for 3 times, the connection to the API looks fine to me. This looks like requests 2 and 4 are identical (same endpoint, data and method). As they are made immediately after another a rate limit error is to be expected. What is the outcome or behaviour you would expect?
  12. @bernhard Apologies for the delay! I've pushed updates to the dev branch. I had a few changes that were already going into the next version that I had to do some extra testing for and a lot of housekeeping. Let me know if this works as well for you as it did me and I'll push another version to main https://github.com/SkyLundy/Fluency/tree/development New feature that some may be interested in- adding DeepL languages for translation that are technically supported by their API but not delivered by the languages endpoint yet. You can read more about when that happens and why on this DeepL documentation page. To manually define languages in Fluency that are supported for translation, you can use a hook. This will make the language available both within the global translation tool as well as available for configuration with a ProcessWire language on the module config page. <?php namespace ProcessWire; // ready.php use Fluency\DataTransferObjects\{EngineLanguageData, EngineTranslatableLanguagesData}; // Hook after Fluency gets the available languages from the DeepL API wire()->addHookAfter('Fluency::getTranslatableLanguages', function (HookEvent $e) { // $e->return is an instance of EngineTranslatableLanguageData // The `languages` property returns an array of EngineLanguageData objects $languages = $e->return->languages; // Create a new data object, define the values according to the API docs, add it to the original languages array $languages[] = EngineLanguageData::fromArray([ 'sourceName' => __('Arabic'), 'sourceCode' => 'AR', 'targetName' => __('Arabic'), 'targetCode' => 'AR', 'meta' => [ 'supports_formality' => false, // This is determined by DeepL, check to see if it's available in their API docs ], ]); // Instantiate a new EngineTranslatableLanguageData object with the language array then assign it to the return value $e->return = EngineTranslatableLanguagesData::fromArray([ 'languages' => $languages ]); }); @Hari KT This is a new method supported by Fluency to add Arabic to Fluency before DeepL lists it for translation. Thank you for inspiring a solution with your Github issue on languages not being available in Fluency. This is available on the dev branch of the Fluency repo if you would like to help test it out @ryangorley This will address the issue you had with Traditional Chinese, albeit a lot later than may be useful for you, but the hook above can be modified to resolve that problem. I'm surprised how long the language had been listed as "available soon" on their API documentation 🤷‍♂️ I would have gone this route sooner had I known there was some documentation about this, I don't think it existed at the time.
  13. Hello everyone, I'm excited to announce that Version 1.0 of ProcessTranslatePage is now available on GitHub: https://github.com/robertweiss/ProcessTranslatePage Please note that there are some breaking changes in this update. I recommend uninstalling and then reinstalling the module to ensure everything works smoothly. You can use the same DeepL API key that you use with Fluency. After installation, you will (hopefully) see two new fields for the language template. However, only the ⁠'translate_locale' field is required for the module to function properly. Thanks for your patience, I hope you find this update useful!
  14. Hi @Ivan Gretsky and @FireWire, Sorry it took me so much time to respond to the big Fluency update. To be honest, I already refactored my module a couple of months ago to work without any dependencies (except the DeepL API), so Fluency is no longer necessary to use it. Since I only did this refactor for one client, I need to remove some customizations before I can push the new version to Github. I don’t expect this to take too long, so I’m hopeful that I’ll be able to release Version 1.0 for you to test tomorrow or thursday 😊. Thanks for your patience!
  15. @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!
  16. Hey @FireWire Probably a great module...? I finally had the time to explore your module but I keep running into the same Deepl API errors and I don't know where to look for a solution or what to do next. This is PW 3.0.229 on PHP 8.2 Fluency 1.0.9 on a pretty basic PW testsite. Deepl API key shows as valid and active and in my Deepl account it says: Access to DeepL REST API When I click on translate the following happens: The error log shows: Engine: DeepLEngine /Error: BAD_REQUEST /Message: Invalid request: Expected 'text' parameter to be an array of strings /Response: {"message":"Invalid request: Expected 'text' parameter to be an array of strings"} The TRANSLATION modal shows only the word undefined in the target language. It's just a testsite, so no rush. I would be greatful for any advice.
  17. Hey @FireWire First of all, thanks a lot for this amazing module! I'm currently working on a project with Fluency + DeepL that needs the glossary feature: https://developers.deepl.com/docs/api-reference/glossaries/openapi-spec-for-glossary-management Since glossaries created on the DeepL website cannot be accessed by the API, they need to be sent to the API with ProcessWire, and translation calls need to have a param with the glossary id for every language pairs. I have most of the work done, and I'd be willing to share it once I clean it up, however I'm not sure how to go about this. My first instinct was to do a stand-alone module with Fluency as a dependency, however I can see that it is heavily locked down with final classes + private and unhookable methods. I'm wondering if there's some interest for this, and if yes, you'd rather have a pull request with the DeepL Glossary feature baked-in, or a pull request which would open up some classes / methods to be extendable, which would allow me to make a new module? Thanks!
  18. @MarkE I know this is a late answer, but I think this is a great question and something that can feel daunting. Hopefully it's still helpful for you and possibly others. I originally wrote my translation module back in 2020 and when it came time to build upon it, add new features, and respond to feedback from the community that first version felt like a straightjacket in terms of structure. I rewrote it last year and have been able to iterate on it much more easily and confidently. This is really a decision based on how you view your project and what "feels good". When you get to writing modules as complex as the one you're describing, as always, the best way to reason about your approach is consistency and maintainability. This is more critical than trying to fit your code into someone else's structure. The most important way to think about organization is considering where you would first look to find a specific feature or behavior and if there are enough of these to warrant their own directory. My translation module probably isn't as complex as yours is, but it may not matter because we're both writing software applications that must be understood and maintained. Anyone can view the repo I shared above, but here are some notes about my reasoning. The purpose of this isn't meant to be a set of instructions or a roadmap, but more of a way to help you think about what is best for your application. [app] - This contains everything that supports what the module must do. If it has logic or supports logic, it goes here. [Caching] - Caching is a performance requirement and required abstraction and logic to tailor PW's caching feature for my use EngineLanguagesCache.php TranslationCache.php [Components] - Fieldsets used in one or more places where abstracting helped keep clean code in other files, like the main Module Traits - Shared behaviors used by Component files FluencyApiUsageTableFieldset.php FluencyStandaloneTranslatorFieldset.php [DataTransferObjects] - All DTOs that encapsulate data provided to and returned by methods in different classes Traits - Shared behaviors used by DTOs AllConfiguredLanguagesData.php ConfiguredLanguageData.php DEVDOC.md - A guide for me and others about how to use DTOs and their purpose as general data objects EngineApiUsageData.php .... [Engines] - Self contained "submodules" that interact with 3rd party services, both current and future. [DeepL] [GoogleCloudTranslation] [Traits] DEVDOC.md FluencyEngine.php FluencyEngineConfig.php FluencyEngineInfo.php [Functions] - General functions imported to support specific sub-behaviors that serve a specific purpose in more than one-two places fluencyEngineConfigNames.php typeChecking.php [Services] - Features that are added to Fluency that extend beyond the primary function of translating page content FluencyProcessWireFileTranslator.php FluencyErrors.php FluencyLocalization.php FluencyMarkup.php [assets] - Files that contain admin-facing UI files and compiled code, Gulp compiles and outputs to this directory [img] [scripts] [styles] [src] - Source JS and SASS that gets compiled and output to the assets directory [scripts] [scss] ...(editor/dotfiles) CHANGELOG.md - Semantic versioning is your friend, this is as important for you as it is for others Fluency.info.php Fluency.module.php FluencyConfig.php LICENSE README.md - This goes into high detail of all features because it also organizes my understanding of everything Fluency does ...(JS module configs and Composer file) I spent a lot of time on this decision. Probably overthought it, and since then there are things that I would do differently- however, how it exists now has been great to work with. My approach was entirely based on what this module does now, and what it may do in the future. The focal point and goals of this approach serve these purposes: - Fluency.info.php - Not required to separate, but helped keep the main module file cleaner and purpose-driven - Fluency.module.php - Aims to primarily contain methods needed to integrate with ProcessWire and any methods available via the global $fluency object - FluencyConfig.php - ProcessWire needs this to be configurable, but the amount of logic it contains certainly benefits from its own file Things I like having lived with it for over a year now. The directory structure is great and supports future expansion since it organizes by purpose. The specific way I structured my subfolders may not make sense for most others, but the message here is the logic behind the approach. Like I said, it seemed overengineered at the time, but now I know exactly where everything is and where everything should be in the future. This module has heavy UI integration and the way the JS files in src/ are broken down makes it clear what everything does. Because JS can import modules from other files, it really doesn't matter how many you have. The JS files for each Inputfield has on more than one occasion enabled me to add features or fixes that would have taken much longer without the granularity I put in place. Initially this module only supported DeepL for translation, but because of how Engines is structured as individual units, it was relatively easy to come back and add Google Cloud Translation because of how the individual units of behavior were organized and supported. What would I do differently having lived with it for over a year now? I would change the file names in app/ and remove the 'Fluency' prefix. That's why we have namespaces. Name collisions are handled by PHP so a simple file naming approach would have been best. This is something that I could change though without impacting the end user. FluencyErrors, FluencyMarkup, and FluencyLocalization might be better located in a 'Support' directory or something, but that would just be applying my approach to organization rather than needing to serve a hard purpose. It doesn't cause any confusion or problems as is. Probably some little things here or there, but not nagging enough to mention or even remember. Anyway. I chose a directory heavy structure with nesting which was a personal choice. There are a lot of great modules out there with different structures. A mark of good organization is asking the question "if I've never looked at this codebase before, would it be something I could get up to speed quickly and contribute without difficulty?". This may seem like a disconnected and impersonal approach, but inevitably you will feel like you need to relearn your own codebase in the future if you've spent enough time away from it. This is a great place to start. In a complex enough project, it may be worth considering separate modules that are installed as dependencies. This would let you group like-kind behavior where it may also be possible that some separate functionality could stand on its own. If you can organize things to separate concerns enough, it's trivial to access other installed modules from within modules using $this->wire('modules')->get('YourOtherModule'); and access all of its features and functionality. Since you can configure your module to have required dependencies, you can be sure that the modules you need will always be available. Organizing by purpose and features is really helpful. If the behavior doesn't provide anything useful as a standalone, then consider keeping it within the "wrapper" module. It depends on how portable you need individual behaviors to be separate from others. I'm not sure too much on the specifics of the implementation, but these are files that perform a specific type of work and would be candidates for their own directory. There's no rule for this, but it makes sense because it gives you a single place to look for these files. Long story short, trust yourself now and think about future you who will work on this later. You'll thank yourself for it. Hope this was relevant enough to be helpful even though it's a late-in-game response.
  19. So, I've bumped into something worth considering. When I added more languages to my client's site the existing pages inherited the untranslated URL slugs from the default language. So I've got to go to the Settings for each page and manually click the translate from English button for each language to pull a translated slug. That's burdensome, but it seemed to be working... until I had to start translating a bunch of blog tags, then some slugs wouldn't translate. I couldn't figure it out until I realized that Fluency must be pulling a DeepL translation from the English slug, not the English title. You'd think it wouldn't matter, but it does. Here's an example: English > French: AI App > Application IA ai-app > ai-app It turns out DeepL translates ai-app to ai-app in every language. I don't think it knows what ai-app means so it just returns it. I don't know how commonly people will run into this problem, but I've been running into it a bit. Sometimes DeepL will return the slug unchanged, sometimes it will provide a slightly different translation than it did for the title. My suggestion would be for the slug translation prompt to use the default language page title when calling for a translation. I could see where pulling the title could create other surprises, such as when someone has the page title "Contact Us" but the slug "contact" they'll be getting longer slugs returned. Still I think that would be preferable to DeepL just silently failing. Maybe others feel differently. It's worth consideration though.
  20. Hi @FireWire First of all, thank you for the module and all the work you have put into it! I just wanted to test the module in a real world project, but quickly realised that certain terms are always translated incorrectly by Deepl. In the web version this is easy to solve with the personal glossary. Is there also a way to create a glossary here, or to tell the API in some way to use my glossary from my account?
  21. Ich möchte anmerken, dass ich NICHT eingeladen habe, hier auf Deutsch zu schreiben, denn das widerspricht den Forums-Regeln. Ich habe angemerkt, dass DeepL sehr gut im Übersetzen ist und eine gute Möglichkeit sein kann, wenn man Probleme mit Englisch hat. Die Idee war aber, den Post auf Deutsch zu verfassen, dann mit DeepL zu übersetzen und dann auf Englisch hier zu posten. I would like to note that I did NOT invite people to write in German here, because that is against the forum rules. I noted that DeepL is very good at translating and can be a good option if you have problems with English. But the idea was to write the post in German, then translate it with DeepL and then post it here in English. CAUTION: This script is likely NOT doing what you want. The selector selects the "authlogs" page, which is the parent page! You want to delete "authlog" pages. CAUTION2: If you change the selector from "authlogs" to "authlog" then it will delete ALL authlog pages, not only old ones. You'll probably want something like this: <?php $cutoff = strtotime("2023-09-01"); $pages->find("template=authlog, your_date_field < $cutoff"); PS: Considering that the selector was wrong that would also explain why it didn't change the page count: You tried to delete the parent page, which is not possible unless you delete all children first. So the script actually did nothing and the count didn't change.
  22. @Martin1 Great idea! Thinking out loud, I'm considering a couple of things by way of how to implement. At it's core, Fluency is intended to provide like-kind behavior that is similar enough between current and future translation services/engines so that the module overall doesn't stray into having over-specificity for functionality. Like having general module methods that reach too far into features or behavior of specific engines. So my first thought is an add-on module to supplement DeepL's abilities- but this is open source so contributors should definitely have input that can make it better. Some thoughts below on addressing the issues you listed- I think that Google Cloud translate may have a similar feature but it would come down to how well the behavior could be abstracted to provide a common enough interface at the engine level where a common Data Transfer Object, and thus a feature interface, can be shared. Final classes- the DataTransfer Objects are definitely a "hard" final class where each should inherit from the base abstract DTO. There is some extra flexibility built in with the ability to add a 'meta' property that can hold some engine-specific behavior, like "formality" which DeepL supports but others like Google don't. Other instances of removing final are probably on the table, I'm not sure I should have made the Fluency module class final. A glossary would definitely warrant it's own DTO in the same spirit as the EngineApiUsageData, EngineTranslationData, EngineLanguagesData, etc. represent data passed between domains for individual features. Otherwise it's probably just a matter of following the Principle of Least Privilege. Unhookable methods- I don't good excuse for this one. Basically left out because hookable methods don't allow for named arguments. This is 100% open to change and was pretty short sighted on my part given that this is a module after all... I should just push a release that does adds hooks regardless. Private methods- This pretty much just follows the Principle of Least Privilege again and, like the final classes notes above, many are open for changing that. All said, I'm kind of open here as far as integrating it into Fluency or opening up class extension, public-ifying methods, and adding hooks. All said, is there one approach that feels better to you?
  23. @bernhard I did try to use it at one point. I remember that it wasn't compatible with how DeepL required it's URL parameters to be structured. I think it was the way that it had multiple GET variables with the same name and that didn't serialize properly when using WireHttp. That may be a moot point now because the DeepL API now accepts JSON encoded POST requests so that URL issue isn't a problem. Prior to that I ran into an issue with WireHttp not handling 404 responses in a way that I need to rely on, so it isn't generally top of mind. Long story short, if a 404 is returned, WireHttp will ignore that valid response and try again. As an aside- I'm working with an API right now where 404 is a valid response for a record that doesn't exist, so trying 2x doubles the API credit usage with that service. May or may not be an issue in this instance, but it is something to keep in mind when HTTP requests have a hard cost associated with them.
  24. Hi friends! Many thanks for this brilliant module! It appears I've found a heavy issue concerning php 8.3.7 . In brief: Fluency crashes, giving multiple errors of this kind: Uncaught Error: Undefined constant "Fluency\Engines\DeepL\CURLOPT_CONNECTTIMEOUT" in site/modules/Fluency/app/Engines/DeepL/DeepLEngine.php:220 Digging inside reveals the following code sample: $requestConfig = [ CURLOPT_CONNECTTIMEOUT => 5, ... CURLOPT_CONNECTTIMEOUT looks here like a constant, however it's not. PHP 8.3.4 can however handle this kind of arrays, and Fluency works like a charm. But it's not the case for PHP 8.3.7 . I think it's worth taking this into consideration during further development. I've also created an issue on the Github module page. Hope this will help to make this module even better ?
  25. "Deepl" is an unbelievably good (paid) text translation service, that mops the floor with Google Translate. They have an API and it would be awesome, if there would be a module, that would integrate it for easy content translation. It could be a right-click context menu on the language tab: It should ask from which of available other language it shall take translate from. What do you think?
×
×
  • Create New...