root/branches/release-29/lib/MT/Plugin.pm @ 1352

Revision 1352, 25.9 kB (checked in by auno, 22 months ago)

Added to handle code for config_template.

  • Property svn:keywords set to Author Date Id Revision
Line 
1# Movable Type (r) Open Source (C) 2001-2008 Six Apart, Ltd.
2# This program is distributed under the terms of the
3# GNU General Public License, version 2.
4#
5# $Id$
6
7package MT::Plugin;
8
9use strict;
10use base qw( MT::Component );
11
12sub init {
13    my $plugin = shift;
14    $plugin->{__settings} = {};
15    if (exists $plugin->{app_action_links}
16        || exists $plugin->{app_itemset_actions}
17        || exists $plugin->{upgrade_functions}
18        || exists $plugin->{app_methods}
19        || exists $plugin->{junk_filters}
20        || exists $plugin->{object_classes}) {
21        # Found in MT::Compat::v3
22        $plugin->legacy_init();
23    }
24    $plugin->SUPER::init(@_) or return;
25    return $plugin;
26}
27
28sub id {
29    my $plugin = shift;
30    my $id = $plugin->SUPER::id(@_);
31    return $id || $plugin->{plugin_sig};
32}
33
34sub key { &MT::Component::_getset(shift, 'key', @_) }
35sub author_name { &MT::Component::_getset_translate(shift, 'author_name', @_) }
36sub author_link { &MT::Component::_getset(shift, 'author_link', @_) }
37sub plugin_link { &MT::Component::_getset(shift, 'plugin_link', @_) }
38sub config_link { &MT::Component::_getset(shift, 'config_link', @_) }
39sub doc_link { &MT::Component::_getset(shift, 'doc_link', @_) }
40sub description { &MT::Component::_getset_translate(shift, 'description', @_) }
41sub settings {
42    my $plugin = shift;
43    my $s = &MT::Component::_getset($plugin, 'settings', @_);
44    unless (ref($s) eq 'MT::PluginSettings') {
45        $s = MT::PluginSettings->new($s);
46        &MT::Component::_getset($plugin, 'settings', $s);
47    }
48    return $s;
49}
50sub icon { &MT::Component::_getset(shift, 'icon', @_) }
51
52# Plugin-specific: configuration settings and data
53sub load_config {
54    my $plugin = shift;
55    my ($param, $scope) = @_;
56    my $setting_obj = $plugin->get_config_obj($scope);
57    my $settings = $setting_obj->data;
58    %$param = %$settings;
59    foreach my $key (keys %$settings) {
60        next unless defined $key;
61        my $value = $settings->{$key};
62        next if !defined $value or $value =~ m/\s/ or length($value) > 100;
63        $param->{$key.'_'.$value} = 1;
64    }
65}
66
67sub save_config {
68    my $plugin = shift;
69    my ($param, $scope) = @_;
70    my $pdata = $plugin->get_config_obj($scope);
71    $scope =~ s/:.*//;
72    my @vars = $plugin->config_vars($scope);
73    my $data = $pdata->data() || {};
74    foreach (@vars) {
75        $data->{$_} = exists $param->{$_} ? $param->{$_} : undef;
76    }
77    $pdata->data($data);
78    MT->request('plugin_config.'.$plugin->id, undef);
79    $pdata->save() or die $pdata->errstr;
80}
81
82sub reset_config {
83    my $plugin = shift;
84    my ($scope) = @_;
85    my $obj = $plugin->get_config_obj($scope);
86    MT->request('plugin_config.'.$plugin->id, undef);
87    $obj->remove if $obj->id;
88}
89
90sub config_template {
91    my $plugin = shift;
92    my ($param, $scope) = @_;
93    if ($scope) {
94        $scope =~ s/:.*//;
95    } else {
96        $scope = 'system';
97    }
98    my $r = $plugin->registry;
99    if (my $tmpl = $r->{"${scope}_config_template"} ||
100        $r->{"config_template"} ||
101        $plugin->{"${scope}_config_template"} ||
102        $plugin->{'config_template'}) {
103        if (ref $tmpl eq 'HASH') {
104            $tmpl = MT->handler_to_coderef($tmpl->{code});
105        }
106        return $tmpl->($plugin, @_) if ref $tmpl eq 'CODE';
107        if ($tmpl =~ /\s/) {
108            return $tmpl;
109        } else { # no spaces in $tmpl; must be a filename...
110            return $plugin->load_tmpl($tmpl);
111        }
112    }
113    return undef;
114}
115
116sub config_vars {
117    my $plugin = shift;
118    my ($scope) = @_;
119    $scope ||= 'system';
120    my @settings;
121    if (my $s = $plugin->settings) {
122        foreach my $setting (@$s) {
123            my ($name, $param) = @$setting;
124            next if $scope && $param->{scope} && $param->{scope} ne $scope;
125            push @settings, $name;
126        }
127    }
128    @settings;
129}
130
131sub set_config_value {
132    my $plugin = shift;
133    my ($vars, $scope);
134    if (ref $_[0] eq 'HASH') {
135        ($vars, $scope) = @_;
136    } else {
137        my ($variable, $value);
138        ($variable, $value, $scope) = @_;
139        $vars = { $variable => $value };
140    }
141    my $pdata_obj = $plugin->get_config_obj($scope);
142    my $configuration = $pdata_obj->data() || {};
143    $configuration->{$_} = $vars->{$_} for keys %$vars;
144    $pdata_obj->data($configuration);
145    $pdata_obj->save();
146}
147
148sub get_config_obj {
149    my $plugin = shift;
150    my ($scope_id) = @_;
151    my $key;
152    my $scope = $scope_id;
153    if ($scope && $scope ne 'system') {
154        $scope =~ s/:.*//; # strip off id, leave identifier
155        $key = 'configuration:'.$scope_id;
156    } else {
157        $scope_id = 'system';
158        $scope = 'system';
159        $key = 'configuration';
160    }
161    my $cfg = MT->request('plugin_config.'.$plugin->id);
162    unless ($cfg) {
163        $cfg = {};
164        MT->request('plugin_config.'.$plugin->id, $cfg);
165    }
166    return $cfg->{$scope_id} if $cfg->{$scope_id};
167    require MT::PluginData;
168    # calling "name" directly here to avoid localization
169    my $pdata_obj = MT::PluginData->load({plugin => $plugin->key || $plugin->{name},
170                                          key => $key});
171    if (!$pdata_obj) {
172        $pdata_obj = MT::PluginData->new();
173        $pdata_obj->plugin($plugin->key || $plugin->{name});
174        $pdata_obj->key($key);
175    }
176    $cfg->{$scope_id} = $pdata_obj;
177    my $data = $pdata_obj->data() || {};
178    $plugin->apply_default_settings($data, $scope_id);
179    $pdata_obj->data($data);
180    $pdata_obj;
181}
182
183sub apply_default_settings {
184    my $plugin = shift;
185    my ($data, $scope_id) = @_;
186    my $scope = $scope_id;
187    if ($scope =~ m/:/) {
188        $scope =~ s/:.*//;
189    } else {
190        $scope_id = 'system';
191    }
192    my $defaults;
193    my $s = $plugin->settings;
194    if ($s && ($defaults = $s->defaults($scope))) {
195        foreach (keys %$defaults) {
196            $data->{$_} = $defaults->{$_} if !exists $data->{$_};
197        }
198    }
199}
200
201sub get_config_hash {
202    my $plugin = shift;
203    $plugin->get_config_obj(@_)->data() || {};
204}
205
206sub get_config_value {
207    my $plugin = shift;
208    my ($var, $scope) = @_;
209    my $config = $plugin->get_config_hash($scope);
210    return exists $config->{$_[0]} ? $config->{$_[0]} : undef;
211}
212
213
214package MT::PluginSettings;
215
216sub new {
217    my $pkg = shift;
218    my ($self) = @_;
219    $self ||= [];
220    if (ref $self eq 'HASH') {
221        # convert a hash-style setting structure into what PluginSettings
222        # expects
223        my $settings = [];
224        foreach my $key (keys %$self) {
225            if (defined $self->{$key}) {
226                push @$settings, [ $key, $self->{$key} ];
227            }
228            else {
229                push @$settings, [ $key ];
230            }
231        }
232        @$settings = sort { ( $a->[1] ? $a->[1]->{order} || 0 : 0 )
233            <=> ( $b->[1] ? $b->[1]->{order} || 0 : 0 ) } @$settings;
234        $self = $settings;
235    }
236    # Lowercase all settings keys
237    foreach my $setting (@$self) {
238        my ($name, $param) = @$setting;
239        $param->{lc $_} = $param->{$_} for keys %$param;
240    }
241    bless $self, $pkg;
242}
243
244sub defaults {
245    my $settings = shift;
246    my ($scope) = @_;
247    my $defaults = {};
248    foreach my $setting (@$settings) {
249        my ($name, $param) = @$setting;
250        next unless exists $param->{default};
251        next if $scope && $param->{scope} && $param->{scope} ne $scope;
252        $defaults->{$name} = $param->{default};
253    }
254    $defaults;
255}
256
2571;
258__END__
259
260=head1 NAME
261
262MT::Plugin - Movable Type class that describes a plugin
263
264=head1 SYNOPSIS
265
266    package MyPlugin;
267
268    use base 'MT::Plugin';
269    use vars qw($VERSION);
270    $VERSION = 1.12;
271
272    my $plugin = new MyPlugin({
273        name => 'My Plugin',
274        version => $VERSION,
275        author_name => 'Conan the Barbaraian',
276        author_link => 'http://example.com/',
277        plugin_link => 'http://example.com/mt-plugins/example/',
278        description => 'Frobnazticates all Diffyhorns',
279        config_link => 'myplugin.cgi',
280        settings => new MT::PluginSettings([
281            ['option1', { Default => 'default_setting' }],
282            ['option2', { Default => 'system_default', Scope => 'system' }],
283            ['option2', { Scope => 'blog' }],
284        ]),
285        config_template => \&config_tmpl
286    });
287    MT->add_plugin($plugin);
288
289    # Alternatively, instantiating MT::Plugin itself
290
291    my $plugin = new MT::Plugin({
292        name => "Example Plugin",
293        version => 1.12,
294        author_name => "Conan the Barbarian",
295        author_link => "http://example.com/",
296        plugin_link => "http://example.com/mt-plugins/example/",
297        description => "Frobnazticates all Diffyhorns",
298        config_link => 'myplugin.cgi',
299        doc_link => <documentation URL>,
300        settings => new MT::PluginSettings([
301            ['option1', { Default => 'default_setting' }],
302            ['option2', { Default => 'system_default', Scope => 'system' }],
303            ['option2', { Scope => 'blog' }],
304        ]),
305        config_template => \&config_tmpl
306    });
307    MT->add_plugin($plugin);
308
309=head1 DESCRIPTION
310
311An I<MT::Plugin> object holds data about a plugin which is used to help
312users understand what the plugin does and let them configure the
313plugin.
314
315Normally, a plugin will construct an I<MT::Plugin> object and pass it
316to the C<add_plugin> method of the I<MT> class:
317
318    MT->add_plugin($plugin);
319
320This will help populate additional information about the plugin on
321the plugin listing in the MT system overview.
322
323When adding callbacks, you will use the plugin object as well; this
324object is used to help the user identify errors that arise in
325executing the callback. For example, to add a callback which is
326executed before the I<MT::Foo> object is saved to the database, you might
327make a call like this:
328
329   MT::Foo->add_callback("pre_save", 10, $plugin, \&callback_function);
330
331This call will tell I<MT::Foo> to call the function
332C<callback_function> just before executing any C<save> operation. The
333number '10' is signalling the priority, which controls the order in
334which various plugins are called. Lower number callbacks are called
335first.
336
337=head1 ARGUMENTS
338
339=over 4
340
341=item * key
342
343The key is an optional, but recommended element of the plugin. This
344value is used to uniquely identify the plugin and should never change
345from one version to the next. The key is used when available in storing
346plugin configuration data using the C<MT::PluginData> package.
347
348=item * name (required)
349
350A human-readable string identifying the plugin. This will be displayed
351in the plugin's slug on the MT front page.
352
353=item * version
354
355The version number for the release of the plugin. Will be displayed
356next to the plugin's name wherever listed. This information is not
357required, but recommended.
358
359=item * schema_version
360
361If your plugin declares a list of object classes, the schema_version
362is used to determine whether your classes require installation or
363upgrade. MT will store your plugin's schema_version in the C<MT::Config>
364table for future reference.
365
366=item * description
367
368A longer string giving a brief description of what the plugin does.
369
370=item * doc_link
371
372A URL pointing to some documentation for the plugin. This can be a
373relative path, in which case it identifies documentation within the
374plugin's distribution, or it can be an absolute URL, pointing at
375off-site documentation.
376
377=item * config_link
378
379The relative path of a CGI script or some other configuration
380interface for the plugin. This is relative to the "plugin
381envelope"--that is, the directory underneath C<mt/plugins> where all
382your plugin files live.
383
384=item * author_name
385
386The name of the individual or company that created the plugin.
387
388=item * author_link
389
390A URL pointing to the home page of the individual or company that
391created the plugin.
392
393=item * plugin_link
394
395A URL pointing to the home page for the plugin itself.
396
397=item * config_template
398
399Defines a C<MT::Template> file by name to use for plugin configuration.
400This value may also be a code reference, which MT would call
401passing three arguments: the plugin object instance, a hashref of
402C<MT::Template> parameter data and the scope value (either "system"
403for system-wide configuration or "blog:N" where N is the active blog id).
404
405=item * system_config_template
406
407Defines a C<MT::Template> file by name to use for system-wide
408plugin configuration. If not defined, MT will fall back to the config_template
409setting. This value may also be a code reference, which MT would call
410passing three arguments: the plugin object instance, a hashref of
411C<MT::Template> parameter data and the scope value (always "system" in
412this case).
413
414=item * blog_config_template
415
416Defines a C<MT::Template> file by name to use for weblog-specific
417plugin configuration. If not defined, MT will fall back to the config_template
418setting. This value may also be a code reference, which MT would call
419passing three arguments: the plugin object instance, a hashref of
420C<MT::Template> parameter data and the scope value (for weblogs, this
421would be "blog:N", where N is the active blog id).
422
423=item * settings
424
425Identifies the plugin's configuration settings.
426
427=item * app_methods
428
429Used to register custom mode handlers for one or more application classes.
430This parameter accepts a hashref of package names mapping to a hashref of
431modes and their handlers. For example:
432
433    app_methods => {
434        'MT::MyPackage' => {
435            'mode1' => \&handler1,
436            'mode2' => \&handler2
437        }
438    }
439
440=item * callbacks
441
442Used to register object or application callbacks with the callback
443system. This can be used in lieu of MT->add_callback. Example:
444
445    callbacks => {
446        'callback_name' => \&callback_handler,
447        'another_callback' => {
448            priority => 1,
449            code => \&another_handler
450        }
451    }
452
453=item * junk_filters
454
455You can register one or more junk detection filters using this
456key. The format is:
457
458    junk_filters => {
459        'MyJunkFilter' => \&junk_filter_handler
460    }
461
462This is an alternative to using C<MT-E<gt>register_junk_filter>.
463
464=item * init_app
465
466It's possible for a plugin to define code that is to be executed upon
467app initialization with this parameter. It may be a simple coderef which
468will be invoked for all MT::App instances:
469
470    init_app => \&init_app_routine
471
472Or it can be a hashref that maps MT::App package names to a coderef.
473
474    init_app => {
475        'MT::App::CMS' => \&init_cms_app_routine,
476        'MT::App::Comments' => \&init_comments_app_routine,
477    }
478
479=item * init_request
480
481A plugin can use this parameter to define a routine to execute upon
482the start of each HTTP request to an application. Like 'init_app', this
483parameter can either be a coderef or a hashref for app-specific routines.
484
485=item * template_tags
486
487This parameter is used to declare custom tag handlers for Movable Type.
488It is similar in function to C<MT::Template::Context-E<gt>add_tag>.
489The parameter is given as a hashref, in this format:
490
491    template_tags => {
492        'TagName' => \&tag_handler
493    }
494
495You may register one or more template tags in this way.
496
497=item * container_tags
498
499This parameter is used to declare custom container tags for Movable Type.
500It is similar in function to C<MT::Template::Context-E<gt>add_container_tag>.
501You may register one or more container tags in this way.
502
503    container_tags => {
504        'ContainerTag' => \&container_tag_handler
505    }
506
507=item * conditional_tags
508
509This parameter is used to declare custom conditional tags for Movable Type.
510This is similar in function to C<MT::Template::Context-E<gt>add_conditional_tag>.
511You may register one or more conditional tags in this way.
512
513    conditional_tags => {
514        'IfCondition' => \&conditional_tag_handler
515    }
516
517=item * global_filters
518
519This parameter is used to declare global tag attributes. It is similar in
520function to C<MT::Template::Context-E<gt>add_global_filter>. You may
521register 1 or more global filters in this way.
522
523    global_filters => {
524        'attribute_name' => \&attribute_handler
525    }
526
527=item * text_filters
528
529Text formatting filters can be declared with this parameter. It is similar
530in function to C<MT-E<gt>add_text_filter>. You may register 1 or more
531filters in this way.
532
533    text_filters => {
534        'format_name' => { label => "My Text Format", code => \&formatter }
535    }
536
537=item * tasks
538
539System tasks that are executed through the C<MT::TaskMgr> can be registered
540with this parameter. The format for this parameter is as follows:
541
542    tasks => {
543        'task_id' => \&task_code,
544        'weekly_task' => {
545            name => "My Weekly Task",
546            frequency => 24 * 60 * 60 * 7,   # run every 7 days
547            code => \&weekly_task_code
548        }
549    }
550
551The task identifier used for the key of each task registered should be
552globally unique. You should use some unique prefix or suffix that only
553your plugin will use.
554
555Refer to L<MT::TaskMgr> for more details on the MT task subsystem.
556
557=item * object_classes
558
559Declaration of a list of MT::Object descendant classes that you want
560the MT upgrade process to maintain.
561
562    object_classes => [ 'MyPlugin::Foo', 'MyPlugin::Bar' ]
563
564Define this in conjunction with a C<schema_version> to have MT maintain
565the schema for your object packages.
566
567=item * upgrade_functions
568
569This defines a list of custom upgrade operations that you may require MT
570to use to upgrade your schema from one version to another. For most upgrades
571(simple column additions or size changes), this is unnecessary, but if you
572require any kind of data manipulation or conversion, you will need to
573register an upgrade function to handle it.  Please refer to the L<MT::Upgrade>
574package for how to declare an upgrade function.  Here is an example:
575
576    upgrade_functions => {
577        'my_plugin_fix_field_a' => {
578            version_limit => 1.1,   # runs for schema_version < 1.1
579            code => \&plugin_field_a_fixer
580        }
581    }
582
583=item * icon
584
585Set the icon filename (not including the plugin's static web path).
586
587=item * log_classes
588
589Set the name of the plugin's log classes to use.  For example:
590
591  MT->add_plugin({
592    name => "My custom plugin",
593    log_classes => { customlog => "MyCustomLog" }
594  });
595
596=back
597
598=head1 METHODS
599
600Each of the above arguments to the constructor is also a 'getter'
601method that returns the corresponding value. C<MT::Plugin> also offers
602the following methods:
603
604=head2 MT::Plugin->new
605
606Return a new I<MT::Plugin> instance.  This method calls the I<init> method.
607
608=head2 $plugin->init
609
610This construction helper method registers plugin I<callbacks>,
611I<junk_filters>, I<text_filters>, I<log_classes>, I<template_tags>,
612I<conditional_tags>, I<global_filters>.
613
614=head2 $plugin->init_app
615
616For subclassed MT::Plugins that declare this method, it is invoked when
617the application starts up.
618
619=head2 $plugin->init_request
620
621For subclassed MT::Plugins that declare this method, it is invoked when
622the application begins handling a new request.
623
624=head2 $plugin->init_tasks
625
626For subclassed MT::Plugins that declare this method, it is invoked when
627the application begins handling a new task.
628
629=head2 $plugin->envelope
630
631Returns the path to the plugin, relative to the MT directory. This is
632determined automatically when the plugin is loaded.
633
634=head2 $plugin->set_config_value($key, $value[, $scope])
635
636See the I<get_config_value> description below.
637
638=head2 $plugin->get_config_value($key[, $scope])
639
640These routines facilitate easy storage of simple configuration
641options.  They make use of the PluginData table in the database to
642store a set of key-value pairs for each plugin. Call them as follows:
643
644    $plugin->set_config_value($key, $value);
645    $value = $plugin->get_config_value($key);
646
647The C<name> field of the plugin object is used as the namespace for
648the keys. Thus it would not be wise for one plugin to use the
649same C<name> as a different plugin.
650
651=head2 $plugin->get_config_obj([$scope])
652
653Retrieves the MT::PluginData object associated with this plugin
654and the scope identified (which defaults to 'system' if unspecified).
655
656=head2 $plugin->apply_default_settings($data[, $scope])
657
658Applies the default plugin settings to the given data.
659
660=head2 $plugin->get_config_hash([$scope])
661
662Retrieves the configuration data associated with this plugin
663and returns it a a Perl hash reference. If the scope parameter is not given,
664the 'system' scope is assumed.
665
666=head2 $plugin->config_template($params[, $scope])
667
668Called to retrieve a MT::Template object which will be output as the
669configuration form for this plugin. Optionally a scope may be specified
670(defaults to 'system').
671
672    my $system_tmpl = $plugin->config_template($params, 'system');
673    my $system_tmpl = $plugin->config_template($params);
674    my $blog_tmpl = $plugin->config_template($params, 'blog:1');
675
676=head2 $plugin->config_vars([$scope])
677
678Returns an array of configuration setting names for the requested scope.
679
680=head2 $plugin->save_config($param[, $scope])
681
682Handles saving configuration data from the plugin configuration form.
683
684    my $param = { 'option1' => 'x' };
685    $plugin->save_config($param); # saves system configuration data
686    $plugin->save_config($param, 'system'); # saves system configuration data
687    $plugin->save_config($param, 'blog:1'); # saves blog configuration data
688
689=head2 $plugin->load_config($param[, $scope])
690
691This method returns the configuration data associated with a plugin (and
692an optional scope) in the given I<param> hash reference.
693
694=head2 $plugin->reset_config($scope)
695
696This method drops the configuration data associated with this plugin
697given the scope identified and reverts to th MT defaults.
698
699Handles loading configuration data from the plugindata table.
700
701=head2 $plugin->load_tmpl($file[, ...])
702
703Used to load a MT::Template object relative to the plugin's directory.
704It will scan both the plugin's directory and a directory named 'tmpl'
705underneath it. It will passthrough parameters that follow the $file
706parameter into the MT::Template constructor.
707
708=head2 MT::Plugin->select([$class])
709
710Return the list of plugins available for the calling class or of the given
711class name argument.
712
713=head2 $plugin->needs_upgrade()
714
715This method compares any previously stored schema version for the
716plugin to the current plugin schema version number to determine if an
717upgrade is in order.
718
719=head2 $plugin->translate($phrase [, @args])
720
721This method translate the C<$phrase> to the currently selected language
722using the localization module for the plugin. The C<@args> parameters
723are passed through if given.
724
725=head2 $plugin->translate_templatized($text)
726
727This method calls the plugin's I<translate> method on any E<lt>MT_TRANSE<gt>
728tags inside C<$text>.
729
730=head2 $plugin->l10n_filter($text)
731
732This method is an alias for the I<translate_templatized> method.
733
734=head2 $plugin->l10n_class()
735
736This method returns the I<l10n_class> attribute of the plugin or
737I<MT::L10N> if not defined.
738
739=head2 $plugin->register_importer()
740
741This method gives plugins access to registry of importers.
742Detailed information can be found in I<MT::Import> document.
743
744=head2 Additional Accessor Methods
745
746The following are plugin attributes with accompanying get/set methods.
747
748=over 4
749
750=item * key
751
752=item * name
753
754=item * author_name
755
756=item * author_link
757
758=item * plugin_link
759
760=item * version
761
762=item * schema_version
763
764=item * config_link
765
766=item * doc_link
767
768=item * description
769
770=item * envelope
771
772=item * settings
773
774=item * icon
775
776=item * callbacks
777
778=item * upgrade_functions
779
780=item * object_classes
781
782=item * junk_filters
783
784=item * text_filters
785
786=item * template_tags
787
788=item * conditional_tags
789
790=item * log_classes
791
792=item * container_tags
793
794=item * global_filters
795
796=item * app_methods
797
798=item * app_action_links
799
800=item * app_itemset_actions
801
802=item * tasks
803
804=back
805
806=head1 LOCALIZATION
807
808Proper localization of a plugin requires a bit of structure and discipline.
809First of all, your plugin should declare a 'l10n_class' element upon
810registration. This defines the base L10N package to use for any translation
811done by the plugin:
812
813    # file l10nplugin.pl, in MT_DIR/plugins/l10nplugin
814
815    my $plugin = new MT::Plugin({
816        name => "My Localized Plugin",
817        l10n_class => "l10nplugin::L10N",
818    });
819
820Then, you should have a file like this in C<MT_DIR/plugins/l10nplugin/lib/l10nplugin>:
821
822    # file L10N.pm, in MT_DIR/plugins/l10nplugin/lib/l10nplugin
823
824    package l10nplugin::L10N;
825    use base 'MT::Plugin::L10N';
826    1;
827
828And then your actual localization modules in C<MT_DIR/plugins/l10nplugin/lib/l10nplugin/L10N>:
829
830    # file en_us.pm, in MT_DIR/plugins/l10nplugin/lib/l10nplugin/L10N
831
832    package l10n::L10N::en_us;
833
834    use base 'l10nplugin::L10N';
835
836    1;
837
838Here's a French module, to localize the plugin name:
839
840    # file fr.pm, in MT_DIR/plugins/l10nplugin/lib/l10nplugin/L10N
841
842    package l10nplugin::L10N::fr;
843
844    use base 'l10nplugin::L10N::en_us';
845
846    our %Lexicon = (
847        "My Localized Plugin" => "Mon Plugin Localise",
848    );
849
850    1;
851
852And, the following methods of the plugin object are I<automatically>
853translated for you, so you don't need to invoke translate on them
854yourself:
855
856=over 4
857
858=item * name
859
860=item * author_name
861
862=item * description
863
864=back
865
866To translate individual strings of text from within your plugin code
867is done like this:
868
869    my $rebuild_str = $plugin->translate("Publish");
870
871Note that if your plugin does not translate a phrase, it may be translated
872by the MT translation matrix if the phrase is found there. So common
873MT phrases like "Weblog", "User", etc., are already handled and you should
874not have to duplicate the translation of such terms in your plugin's
875localization modules.
876
877To translate a template that has embedded E<lt>MT_TRANSE<gt> tags in
878them, use the C<translate_templatized> method of the plugin object.
879
880    $tmpl = $plugin->load_tmpl("my_template.tmpl");
881    $tmpl->param(\%param);
882    my $html = $plugin->translate_templatized($tmpl->output());
883
884=head1 MT::PluginSettings
885
886The MT::PluginSettings package is also declared with this module. It
887is used to define a group of settings and their defaults for the plugin.
888These settings are processed whenever configuration data is requested
889from the plugin.
890
891Example:
892
893    $plugin->{settings} = new MT::PluginSettings([
894        ['option1', { Default => 'default_setting' }],
895        ['option2', { Default => 'system_default', Scope => 'system' }],
896        ['option2', { Scope => 'blog' }],
897    ]);
898
899Settings can be assigned a default value and an applicable 'scope'.
900Currently, recognized scopes are "system" and "blog".
901
902=head1 AUTHOR & COPYRIGHT
903
904Please see L<MT/AUTHOR & COPYRIGHT>.
905
906=cut
Note: See TracBrowser for help on using the browser.