ProcessWire 3.0.179 adds great new admin theme customization tools that put you in full control over the admin styles. More
ProcessWire 3.0.181 has fixes and improvements as usual, but the biggest addition is a nice pull request from LostKobrakai, plus major updates to our Helloworld and ProcessHello demonstration modules. This post covers it all.
The pull request that we added from LostKobrakai is actually one of the oldest in our repo, as well as the one that had the most thumbs-up likes. It adds the ability for module authors to supply language translations with their module, and provides a means by which users can easily install those translations into the appropriate language.
After adding this PR, I realized that it really needs to be demonstrated in order to best communicate how it works. I thought my two previous "Hello World" modules would be a good way to do that (Helloworld and ProcessHello). But once I got into those modules, I realized they were getting old and were ready for some serious upgrades, improvements and new documentation. So that's what I put a lot of focus into this week, bringing those two modules up-to-date. I don't mean just adding support for bundled multi-language translations, but revisiting every part of them to be up-to-date with ProcessWire's current master and dev branches. Because so much has changed with these modules, I thought I'd use this post to re-introduce them, in addition to looking at the new ability to bundle multi-language translations with modules.
Updated “hello world” demonstration modules
This Helloworld module is a demonstration of a general purpose module that adds hooks of various kinds. It does a lot of useless stuff purely for demonstration purposes, because that's the point of it. It serves as a good intro to module development in ProcessWire, as well as a good introduction to hooks. This new version also demonstrates URL/path hooks that were added in ProcessWire 3.0.173. This is a module to install locally on your dev server to experiment with. Here's a list of what it does:
Adds a hook after
Page::renderto output a 'hello world' message at the bottom of editable pages (if enabled in the module configuration). Just to make it somewhat useful, clicking it takes you to the editor for that page.
Adds a hook after
Pages::saveto display a hello notification every time you save a page.
$page->hello()method to all pages, which simply returns your hello world message and information about the page. Optionally provide an argument with some text, i.e.
$page->hello('some text')to have it included in the return value.
$page->hello_worldproperty/variable to all pages. Accessing it simply returns: “Hello user-name”.
ProcessPageEdit::executehook which displays a notification to you only when you edit the homepage.
Demonstrates the optional install(), uninstall() and upgrade() methods. The install method creates database table
hello_world, while the uninstall method drops it. The upgrade method congratulates the user when they upgrade from version 0.0.3 or prior.
In ProcessWire 3.0.173 and newer the Helloworld module demonstrates URL/path hooks. With the module installed, try accessing these URLs on your site:
URL hook 1: answers only this URL
URL hook 2: allows earth, mars or jupiter using a named argument that matches from a set.
URL hook 3: allows any word for the 'anything' part, using a named argument that matches any URL segment.
In ProcessWire 3.0.181 and newer the Helloworld module demonstrates inclusion of language translations with the module. This requires that ProcessWire’s core multi-language support modules are installed. Language translation files are .csv files exported from ProcessWire’s language translator tools that are stored in a /languages/ directory of of your module’s directory. We'll discuss later in this post more about how module authors can do this.
Above are all the things that the module demonstrates, but it also includes an /extras/ directory that includes blank starter templates for both a standard module (BlankModule) and configurable module (BlankConfigurableModule), as well as a demonstration of an external module configuration file. The module's README file also includes a section on how to modify the Helloworld.module.php to become a starting point for making your own module.
Process modules are used primarily for building admin applications and tools in ProcessWire, and this module serves as a demonstration of a simple admin application. Like the Helloworld module, it does a lot of silly and useless stuff for demonstration purposes, and that's the point of it. Process modules tend to be quite different from other types of modules, so it naturally demonstrates very different things from the Helloworld module. Here's a list of what the new ProcessHello module demonstrates:
- How to have ProcessWire create a dedicated Page for your module at install time.
- How to create custom permissions for your module.
- How to create an index
execute()method that is called for your Process module’s main/index URL.
- How to create
executeSomething()method(s) that are automatically called when URL segment matches (i.e. /something/).
- How to return markup from your URL handling methods directly.
- How to use separate “view” files for generating output for your URL handling methods.
- How to create message, warning and error notifications in the admin.
- How to set the admin headline, breadcrumbs and browser
- How to define drop-down navigation for your Process module.
- How to create and process a simple form that uses Inputfield modules.
- How to provide additional submit actions in the form submit button.
- How to make the Process module configurable.
- How to provide multi-language translations for the Process module.
- How to adapt the ProcessHello module to be the starting point for your own Process module.
How to bundle multi-language translations with your module
Regardless of what kind of module you are developing, you can now bundle translations for other languages thanks to LostKobrakai's pull request added this week. To use it, you'll need ProcessWire 3.0.181 or newer and multi-language support installed. Both the Helloworld and ProcessHello modules mentioned above demonstrate this capability.
Export CSV file translations, give them names that reflect the language and copy them to /site/modules/YourModule/languages/.
Locate the files you want to translate from your admin: Setup > Languages > language > Site files > Find files to translate. Select the file(s) and submit. ProcessWire will generate new empty .json files for the files you selected to translate.
If you selected just one file above, it will take you there now. Otherwise, in Setup > Languages > language, click the "edit" link for file(s) added for your module. Once on the file translation screen, translate the text into the desired language and save (I just copied/pasted from Google Translate for the two modules above). Near the top of the translation screen is a link to "Download" or "View" a CSV file of the translations. Click that to save (or view) the CSV file of translations.
Copy the CSV file(s) or translations you exported in the previous step into a /languages/ directory in your module’s path. For instance /site/modules/ProcessHello/languages/ is the one you'll see with the ProcessHello module. While not required, you might consider naming your files with the ISO-639-1 language code. For instance, German would be de.csv, Spanish would be es.csv, Finnish would be fi.csv, etc. Regardless of what name you use, the goal is just simply that the filename should explain what language it is for.
Since a single .csv file can provide translations for multiple .php files, if your module happens to have multiple translatable files, you can bundle all the translations into a single CSV file (just copy and paste into one), or if need be, you can have multiple .csv files for each language. Though I prefer to keep it simple with one file per language.
In your module’s documentation, instruct the user to install translations from your module’s info/config screen. It’s in the “Module Information” fieldset “Languages” row, where there is an “install translations” link. When new versions of your module also update the translations, make note of that in your changelog so that users will know to click the “install translations” again to update the translations.
How users can install a module’s translations
This is best demonstrated with a couple of screenshots. Below is a module’s configuration screen with the “Module Information” fieldset opened:
Note the second to last row in the “Module Information” fieldset above where it says “Languages”, followed by a list of languages it contains translations for. When you click the “install translations” link you are taken to this screen:
From here you can match the available translations with the languages you have installed on your site. In my case, I was able to match the “es” (Spanish) translation of the module with the Spanish version of the site. Once you click the Submit button, ProcessWire imports the translations and they take effect immediately.
Why use CSV for bundled translations?
Internally ProcessWire stores translations as JSON files that are mapped 1-to-1 with PHP files. These are bare-bones JSON files that include a hash of the source text alongside the translated text, and they don't store much more than that. (The hash represents not just the source text but also its context and comments). ProcessWire uses CSV files when it needs to provide a file that includes both source and translated text, and needs the ability to provide translations for potentially multiple PHP files in one CSV file. The CSV format is used because it's very easy for people to import into other systems and/or spreadsheets. It's something that can be sent to a person translating text, and then sent back to you and imported once they are finished; all without giving them access to ProcessWire. That's just one example, but essentially the CSV option is more portable when we need to send translations around, before they get imported and converted to their JSON source files.
For bundled module translations, I think LostKobrakai's choice to use the CSV format made good sense for 2 reasons. First is that one CSV file can include translations for multiple PHP files. Second, they include both the translated and untranslated versions of the text, which can be useful to module authors that might need to easily identify if they should re-generate a new CSV after changing text in the module.
Thanks for reading, read more at ProcessWire Weekly and have a great weekend!