This is an attempt to have translatable plugins (like bug 37472) but using Koha::I18N (runtime translations) See also bug 37472 comment 11 and bug 37472 comment 8
Created attachment 180642 [details] [review] Bug 39564: Enable runtime translations for plugins (Koha::I18N)
Created attachment 180643 [details] [review] Bug 39564: Enable runtime translations for plugins (Koha::I18N) This solution uses gettext's textdomain feature to allow plugins to use Koha::I18N for their own translations. Basically we have one textdomain per plugin and we bind the directory where a plugin store its translations (.mo files) to its textdomain. Plugins have to specify the textdomain like this: __d('MyPlugin', 'string to translate') or, if within a template: [% I18N.td('MyPlugin', 'string to translate') %] This patches adds several functions to Koha::I18N: __d, __dn, __dp, __dnp, __dx, __dnx, __dpx, and __dnpx and their template equivalents in Koha::Template::Plugin::I18N It also moves some code for string extraction from gulpfile.js to misc/translator/xgettext-perl and misc/translator/xgettext-js for easier use by plugins authors. (Note that, even if there is a misc/translator/xgettext-js script, this patch does not add support for JS translations in plugins) By default a plugin named Koha::Plugin::Foo will have a textdomain 'Koha-Plugin-Foo'. It can be changed by overriding method locale_textdomain. By default the directory bound to the textdomain will be Koha/Plugin/Foo/locale. It can be changed by overriding method locale_dir. This directory should contain one subdirectory for each language, and each language subdirectory should contain an LC_MESSAGES subdirectory which should contain a <textdomain>.mo file. It should look like this: Koha/ Plugin/ Foo/ locale/ fr_FR/ LC_MESSAGES/ Koha-Plugin-Foo.mo de_DE/ LC_MESSAGES/ Koha-Plugin-Foo.mo ...
Example plugin here : https://gitlab.com/jajm/koha-plugin-i18n-example Test plan: 1. Apply the patch 2. Install the example plugin and restart koha 3. Enable fr-FR language for the staff interface. 4. Go to Admin > Plugins and run the example plugin's tool. 5. Switch between en and fr-FR to see the changes.
Did you investigate a way to prevent the addition of the new methods? It would be nice to use the existing ones and deal with the domain in Koha::Plugins or Koha::I18N. We could guess the caller and set the domain depending on it. Not totally sure how we would make that work, but Iām curious, did you already ask yourself that question? :)
(In reply to Jonathan Druart from comment #4) > Did you investigate a way to prevent the addition of the new methods? Actually I started without the new methods but I figured it would be nice to make these two things customizable. So yes, it's totally doable.
(In reply to Julian Maurice from comment #5) > (In reply to Jonathan Druart from comment #4) > > Did you investigate a way to prevent the addition of the new methods? > > Actually I started without the new methods but I figured it would be nice to > make these two things customizable. > So yes, it's totally doable. I may have read your comment too quickly. Are you talking about the __d* functions ?
(In reply to Julian Maurice from comment #6) > (In reply to Julian Maurice from comment #5) > > (In reply to Jonathan Druart from comment #4) > > > Did you investigate a way to prevent the addition of the new methods? > > > > [...] > > I may have read your comment too quickly. Are you talking about the __d* > functions ? For templates, the new methods can be avoided by writing something like this: [% USE i18n = I18N('Example') %] [% i18n.t('string to translate') %] All that is needed is a `new` method in Koha::Template::Plugin::I18N that stores its textdomain parameter (within $self) so it can be used in t* methods. On the Perl side, it might not be that simple, as it would probably require keeping a "wrapper object" around (the wrapper object would change the default textdomain, call the appropriate function __*, then revert the default textdomain to its original value). > We could guess the caller and set the domain depending on it. I really don't like subroutines that change their behaviour depending on the caller. It makes them more difficult to debug and test.