1
$Id: plugin.txt,v 1.38 2004/01/31 02:44:24 pdontthink Exp $
1
$Id: plugin.txt,v 1.24.2.25 2005/01/14 06:15:22 cigamit Exp $
3
In addition to this document, please check out the SquirrelMail
4
development FAQ for more information. Also, help writing plugins
3
In addition to this document, please check out the SquirrelMail
4
development FAQ for more information. Also, help writing plugins
5
5
is easily obtained by posting to the squirrelmail-plugins mailing
6
6
list. (See details about mailing lists on the website)
8
8
FAQ -> http://www.squirrelmail.org/wiki/wiki.php?DeveloperFAQ
10
10
http://www.squirrelmail.org/wiki/wiki.php?DevelopingPlugins
13
13
A FEW NOTES ON THE PLUGIN ARCHITECTURE
14
14
======================================
16
The plugin architecture of SquirrelMail is designed to make it possible
17
to add new features without having to patch SquirrelMail itself.
18
Functionality like password changing, displaying ads and calendars should
16
The plugin architecture of SquirrelMail is designed to make it possible
17
to add new features without having to patch SquirrelMail itself.
18
Functionality like password changing, displaying ads and calendars should
19
19
be possible to add as plugins.
41
41
The plugin jumping off point in the main SquirrelMail code is in the
42
42
file functions/plugin.php. In places where hooks are made available,
43
they are executed by calling the function do_hook('hookname'). The
44
do_hook function then traverses the array
45
$squirrelmail_plugin_hooks['hookname'] and executes all the functions
46
that are named in that array. Those functions are placed there when
47
plugins register themselves with SquirrelMail as discussed below. A
48
plugin may add its own internal functions to this array under any
43
they are executed by calling the function do_hook('hookname'). The
44
do_hook function then traverses the array
45
$squirrelmail_plugin_hooks['hookname'] and executes all the functions
46
that are named in that array. Those functions are placed there when
47
plugins register themselves with SquirrelMail as discussed below. A
48
plugin may add its own internal functions to this array under any
49
49
hook name provided by the SquirrelMail developers.
51
51
A plugin must reside in a subdirectory in the plugins/ directory. The
52
name of the subdirectory is considered to be the name of the plugin.
52
name of the subdirectory is considered to be the name of the plugin.
53
53
(The plugin will not function correctly if this is not the case.)
55
55
To start using a plugin, its name must be added to the $plugins array
60
60
When a plugin is registered, the file plugins/plugin_name/setup.php is
61
61
included and the function squirrelmail_plugin_init_plugin_name() is
62
called with no parameters. That function is where the plugin may
62
called with no parameters. That function is where the plugin may
63
63
register itself against any hooks it wishes to take advantage of.
69
All plugins must contain a file called setup.php and must include a
70
function called squirrelmail_plugin_init_plugin_name() therein. Since
71
including numerous plugins can slow SquirrelMail performance
72
considerably, the setup.php file should contain little else. Any
73
functions that are registered against plugin hooks should do little
69
All plugins must contain a file called setup.php and must include a
70
function called squirrelmail_plugin_init_plugin_name() therein. Since
71
including numerous plugins can slow SquirrelMail performance
72
considerably, the setup.php file should contain little else. Any
73
functions that are registered against plugin hooks should do little
74
74
more than call another function in a different file.
76
Any other files used by the plugin should also be placed in the
77
plugin directory (or subdirectory thereof) and should contain the
76
Any other files used by the plugin should also be placed in the
77
plugin directory (or subdirectory thereof) and should contain the
78
78
bulk of the plugin logic.
80
80
The function squirrelmail_plugin_init_plugin_name() is called to
81
initalize a plugin. This function could look something like this (if
81
initalize a plugin. This function could look something like this (if
82
82
the plugin was named "demo" and resided in the directory plugins/demo/):
84
function squirrelmail_plugin_init_demo ()
84
function squirrelmail_plugin_init_demo ()
86
86
global $squirrelmail_plugin_hooks;
112
112
Including Other Files
113
113
---------------------
115
A plugin may need to reference functionality provided in other
115
A plugin may need to reference functionality provided in other
116
116
files, and therefore need to include those files. Most of the
117
117
core SquirrelMail functions are already available to your plugin
118
118
unless it has any files that are requested directly by the client
119
browser (custom options page, etc.). In this case, you'll need
119
browser (custom options page, etc.). In this case, you'll need
120
120
to make sure you include the files you need (see below).
122
122
Note that as of SquirrelMail 1.4.0, all files are accessed using a
123
123
constant called SM_PATH that always contains the relative path to
124
the main SquirrelMail directory. This constant is always available
125
for you to use when including other files from the SquirrelMail core,
126
your own plugin, or other plugins, should the need arise. If any of
127
your plugin files are requested directly from the client browser,
124
the main SquirrelMail directory. This constant is always available
125
for you to use when including other files from the SquirrelMail core,
126
your own plugin, or other plugins, should the need arise. If any of
127
your plugin files are requested directly from the client browser,
128
128
you will need to define this constant before you do anything else:
130
130
define('SM_PATH', '../../');
134
134
include_once(SM_PATH . 'include/validate.php');
136
136
When including files, please make sure to use the include_once() function
137
and NOT include(), require(), or require_once(), since these all are much
138
less efficient than include_once() and can have a cumulative effect on
137
and NOT include(), require(), or require_once(), since these all are much
138
less efficient than include_once() and can have a cumulative effect on
139
139
SquirrelMail performance.
141
141
The files that you may need to include in a plugin will vary greatly
142
142
depending upon what the plugin is designed to do. For files that are
143
requested directly by the client browser, we strongly recommend that
144
you include the file include/validate.php, since it will set up the
145
SquirrelMail environment automatically. It will ensure the the user
146
has been authenticated and is currently logged in, load all user
143
requested directly by the client browser, we strongly recommend that
144
you include the file include/validate.php, since it will set up the
145
SquirrelMail environment automatically. It will ensure the the user
146
has been authenticated and is currently logged in, load all user
147
147
preferences, include internationalization support, call stripslashes()
148
on all incoming data (if magic_quotes_gpc is on), and initialize and
149
include all other basic SquirrelMail resources and functions. You may
150
see other plugins that directly include other SquirrelMail files, but
151
that is no longer necessary and is a hold-over from older SquirrelMail
148
on all incoming data (if magic_quotes_gpc is on), and initialize and
149
include all other basic SquirrelMail resources and functions. You may
150
see other plugins that directly include other SquirrelMail files, but
151
that is no longer necessary and is a hold-over from older SquirrelMail
154
List of files, that are included by include/validate.php (If SquirrelMail
155
version is not listed, files are included from v.1.3.2.):
156
1. class/mime.class.php
157
1.1. class/mime/Rfc822Header.class.php
158
1.2. class/mime/MessageHeader.class.php
159
1.3. class/mime/AddressStructure.class.php
160
1.4. class/mime/Message.class.php
161
1.5. class/mime/SMimeMessage.class.php
162
1.6. class/mime/Disposition.class.php
163
1.7. class/mime/Language.class.php
164
1.8. class/mime/ContentType.class.php
165
2. functions/global.php
166
3. functions/strings.php
168
4.1. config/config_local.php (from 1.4.0rc1)
169
5. functions/i18n.php
170
5.1. functions/global.php (from 1.4.0)
171
6. functions/auth.php
172
7. include/load_prefs.php
173
7.1. include/validate.php
174
7.2. functions/prefs.php
175
7.3. functions/plugin.php
176
7.3.1. functions/global.php (from 1.4.0 and 1.5.0)
177
7.3.2. functions/prefs.php (from 1.5.1)
178
7.4. functions/constants.php
179
7.5. do_hook('loading_prefs')
180
8. functions/page_header.php
181
8.1. functions/strings.php
182
8.2. functions/html.php
183
8.3. functions/imap_mailbox.php
184
8.3.1. functions/imap_utf7_local.php
185
8.4. functions/global.php
186
9. functions/prefs.php
187
9.1. functions/global.php
188
9.2. $prefs_backend (from 1.4.3rc1 and 1.5.0)
189
functions/db_prefs.php
190
functions/file_prefs.php
155
192
Hook Types: Parameters and Return Values
156
193
-----------------------------------------
244
283
mailbox_index_after functions/mailbox_display.php do_hook
245
284
check_handleAsSent_result functions/mailbox_display.php do_hook
246
285
subject_link functions/mailbox_display.php concat_hook
247
mailbox_display_buttons functions/mailbox_display.php do_hook
248
286
message_body functions/mime.php do_hook
249
287
^ attachment $type0/$type1 functions/mime.php do_hook
250
attachments_bottom functions/mime.php hook_func
251
288
decode_body functions/mime.php hook_func
252
289
generic_header functions/page_header.php do_hook
253
290
menuline functions/page_header.php do_hook
254
internal_link functions/page_header.php hook_func
291
prefs_backend functions/prefs.php hook_func
255
292
loading_prefs include/load_prefs.php do_hook
256
293
addrbook_html_search_below src/addrbook_search_html.php do_hook
257
294
addressbook_bottom src/addressbook.php do_hook
266
303
left_main_after_each_folder src/left_main.php concat_hook
267
304
left_main_before src/left_main.php do_hook
268
305
left_main_after src/left_main.php do_hook
269
create_collapse_link src/left_main.php hook_func
270
306
login_cookie src/login.php do_hook
271
307
login_top src/login.php do_hook
272
308
login_form src/login.php do_hook
273
309
login_bottom src/login.php do_hook
274
310
move_before_move src/move_messages.php do_hook
275
move_messages_button_action src/move_messages.php concat_hook
276
311
* optpage_set_loadinfo src/options.php do_hook
277
312
* optpage_loadhook_personal src/options.php do_hook
278
313
* optpage_loadhook_display src/options.php do_hook
320
355
search_bottom src/search.php do_hook
321
356
logout src/signout.php do_hook
322
357
webmail_top src/webmail.php do_hook
323
webmail_bottom src/webmail.php do_hook
358
webmail_bottom src/webmail.php concat_hook
324
359
logout_above_text src/signout.php concat_hook
360
O info_bottom plugins/info/options.php do_hook
326
362
% = This hook is used in multiple places in the given file
327
363
# = Called with hook type (see below)
328
364
& = Special identity hooks (see below)
329
365
^ = Special attachments hook (see below)
330
366
* = Special options hooks (see below)
367
O = optional hook used by plugin
368
405
[0] = hook name (always "options_identities_renumber")
369
406
[1] = being renumbered from ('default' or 1 through (# idents) - 1)
370
407
[2] = being renumbered to ('default' or 1 through (# idents) - 1)
372
409
options_identities_table
374
411
This hook allows you to insert additional rows into the table that
375
412
holds each identity. The arguments to this hook are:
377
414
[0] = color of table (use it like this in your plugin:
378
<tr bgcolor="<?PHP echo $info[1]?>">
415
<tr bgcolor="<?php echo $info[1]; ?>">
379
416
[1] = is this an empty section (the one at the end of the list)?
380
417
[2] = what is the 'post' value? (ident # or empty string if default)
382
419
You need to return any HTML you would like to add to the table.
383
420
You could add a table row with code similar to this:
385
function demo_identities_table(&$args)
422
function demo_identities_table(&$args)
387
424
return '<tr bgcolor="' . $args[0] . '"><td> </td><td>'
388
425
. 'YOUR CODE HERE' . '</td></tr>' . "\n";
391
428
options_identities_buttons
393
430
This hook allows you to add a button (or other HTML) to the row of
429
466
[7] = Filename that is displayed for the attachment
430
467
[8] = Sent if message was found from a search (where)
431
468
[9] = Sent if message was found from a search (what)
433
470
To set up links for actions, you assign them like this:
435
472
$Args[1]['<plugin_name>']['href'] = 'URL to link to';
436
$Args[1]['<plugin_name>']['text'] = 'What to display';
473
$Args[1]['<plugin_name>']['text'] = _("What to display");
475
Note: _("What to display") is explained in the section about
476
internationalization.
438
478
It's also possible to specify a hook as "attachment type0/*",
439
479
for example "attachment text/*". This hook will be executed whenever there's
440
480
no more specific rule available for that type.
470
510
Before you start adding user preferences to your plugin, please take a moment
471
to think about it: in some cases, more options may not be a good thing.
472
Having too many options can be confusing. Thinking from the user's
511
to think about it: in some cases, more options may not be a good thing.
512
Having too many options can be confusing. Thinking from the user's
473
513
perspective, will the proposed options actually be used? Will users
474
514
understand what these options are for?
476
516
There are two ways to add options for your plugin. When you only have a few
477
517
options that don't merit an entirely new preferences page, you can incorporate
478
them into an existing section of SquirrelMail preferences (Personal
479
Information, Display Preferences, Message Highlighting, Folder Preferences or
480
Index Order). Or, if you have an extensive number of settings or for some
518
them into an existing section of SquirrelMail preferences (Personal
519
Information, Display Preferences, Message Highlighting, Folder Preferences or
520
Index Order). Or, if you have an extensive number of settings or for some
481
521
reason need a separate page for the user to interact with, you can create your
482
522
own preferences page.
486
526
---------------------------------------------------------------------
488
528
There are two ways to accomplish the integration of your plugin's settings
489
into another preferences page. The first method is to add the HTML code
529
into another preferences page. The first method is to add the HTML code
490
530
for your options directly to the preferences page of your choice. Although
491
531
currently very popular, this method will soon be deprecated, so avoid it
492
if you can. That said, here is how it works. :) Look for any of the hooks
493
named as "options_<pref page>_inside", where <pref page> is "display",
494
"personal", etc. For this example, we'll use "options_display_inside" and,
532
if you can. That said, here is how it works. :) Look for any of the hooks
533
named as "options_<pref page>_inside", where <pref page> is "display",
534
"personal", etc. For this example, we'll use "options_display_inside" and,
495
535
as above, "demo" as our plugin name:
497
537
1. In setup.php in the squirrelmail_plugin_init_demo() function:
499
$squirrelmail_plugin_hooks['options_display_inside']['demo']
539
$squirrelmail_plugin_hooks['options_display_inside']['demo']
500
540
= 'demo_show_options';
502
542
Note that there are also hooks such as "options_display_bottom",
524
564
------cut here-------
526
566
Of course, you can place any text where OPTION_NAME is and any input
527
tags where OPTION_INPUT is.
567
tags where OPTION_INPUT is.
529
569
3. You will want to use the "options_<pref page>_save" hook (in this case,
530
570
"options_display_save") to save the user's settings after they have
531
pressed the "Submit" button. Again, back in setup.php in the
571
pressed the "Submit" button. Again, back in setup.php in the
532
572
squirrelmail_plugin_init_demo() function:
534
$squirrelmail_plugin_hooks['options_display_save']['demo']
574
$squirrelmail_plugin_hooks['options_display_save']['demo']
535
575
= 'demo_save_options';
537
577
4. Assuming the function demo_save_options() calls another function
549
589
The second way to add options to one of the SquirrelMail preferences page is
550
590
to use one of the "optpage_loadhook_<pref page>" hooks. The sent_subfolders
551
plugin is an excellent example of this method. Briefly, this way of adding
591
plugin has an excellent example of this method. Briefly, this way of adding
552
592
options consists of adding some plugin-specific information to a predefined
553
593
data structure which SquirrelMail then uses to build the HTML input forms
554
594
for you. This is the preferred method of building options lists going forward.
556
596
1. We'll use the "optpage_loadhook_display" hook to add a new group of
557
options to the display preferences page. In setup.php in the
597
options to the display preferences page. In setup.php in the
558
598
squirrelmail_plugin_init_demo() function:
560
$squirrelmail_plugin_hooks['optpage_loadhook_display']['demo']
600
$squirrelmail_plugin_hooks['optpage_loadhook_display']['demo']
561
601
= 'demo_options';
563
603
2. Assuming the function demo_options() calls another function elsewhere
565
605
arrays, $optpage_data['grps'] and $optpage_data['vals']. The value
566
606
associated with that key should simply be a section heading for your
567
607
plugin on the preferences page for the $optpage_data['grps'] array,
568
and yet another array with all of your plugin's options for the
569
$optpage_data['vals'] array. The options are built as arrays (yes,
608
and yet another array with all of your plugin's options for the
609
$optpage_data['vals'] array. The options are built as arrays (yes,
570
610
that's four levels of nested arrays) that specify attributes that are
571
611
used by SquirrelMail to build your HTML input tags automatically.
572
612
This example includes just one input element, a SELECT (drop-down)
639
679
SMOPT_SIZE_NORMAL
640
680
comment For SMOPT_TYPE_COMMENT type options, this is the text
641
681
displayed to the user
642
script This is where you may add any additional javascript
682
script This is where you may add any additional javascript
643
683
or other code to the user input
644
684
post_script You may specify some script (usually Javascript) that
645
685
will be placed after (outside of) the INPUT tag.
687
Note that you do not have to create a whole new section on the options
688
page if you merely want to add a simple input item or two to an options
689
section that already exists. For example, the Display Options page has
692
0 - General Display Options
693
1 - Mailbox Display Options
694
2 - Message Display and Composition
696
To add our previous input drop-down to the Mailbox Display Options,
697
we would not have to create our own group; just add it to group
700
global $optpage_data;
701
$optpage_data['vals'][1][] = array(
702
'name' => 'plugin_demo_favorite_color',
703
'caption' => 'Please Choose Your Favorite Color',
704
'type' => SMOPT_TYPE_STRLIST,
705
'refresh' => SMOPT_REFRESH_ALL,
706
'posvals' => array(0 => 'red',
710
'save' => 'save_plugin_demo_favorite_color'
647
713
3. If you indicated a 'save' attribute for any of your options, you must
648
714
create that function (you'll only need to do this if you need to do
649
715
some special processing for one of your settings). The function gets
650
one parameter, which is an object with mostly the same attributes you
716
one parameter, which is an object with mostly the same attributes you
651
717
defined when you made the option above... the 'new_value' (and possibly
652
718
'value', which is the current value for this setting) is the most useful
653
719
attribute in this context:
674
740
----------------------------------
676
742
It is also possible to create your own preferences page for a plugin. This
677
is particularly useful when your plugin has numerous options or needs to
743
is particularly useful when your plugin has numerous options or needs to
678
744
offer special interaction with the user (for things such as changing password,
679
745
etc.). Here is an outline of how to do so (again, using the "demo" plugin
682
1. Add a new listing to the main Options page. Older versions of
748
1. Add a new listing to the main Options page. Older versions of
683
749
SquirrelMail offered a hook called "options_link_and_description"
684
750
although its use is deprecated (and it is harder to use in that
685
751
it requires you to write your own HTML to add the option). Instead,
712
778
js Indicates if this option page requires the client browser
713
779
to be Javascript-capable. Should be TRUE or FALSE.
715
3. There are two different ways to create the actual preferences page
716
itself. One is to simply write all of your own HTML and other
717
interactive functionality, while the other is to define some data
781
3. There are two different ways to create the actual preferences page
782
itself. One is to simply write all of your own HTML and other
783
interactive functionality, while the other is to define some data
718
784
structures that allow SquirrelMail to build your user inputs and save
719
your data automatically.
785
your data automatically.
721
Building your own page is wide open, and for ideas, you should look at
787
Building your own page is wide open, and for ideas, you should look at
722
788
any of the plugins that currently have their own preferences pages. If
723
you do this, make sure to read step number 4 below for information on
724
saving settings. In order to maintain security, consistant look and
789
you do this, make sure to read step number 4 below for information on
790
saving settings. In order to maintain security, consistant look and
725
791
feel, internationalization support and overall integrity, there are just
726
792
a few things you should always do in this case: define the SM_PATH
727
793
constant, include the file include/validate.php (see the section about
737
803
From here you are on your own, although you are encouraged to do things
738
804
such as use the $color array to keep your HTML correctly themed, etc.
740
If you want SquirrelMail to build your preferences page for you,
741
creating input forms and automatically saving users' settings, then
806
If you want SquirrelMail to build your preferences page for you,
807
creating input forms and automatically saving users' settings, then
742
808
you should change the 'url' attribute in the options block you created
743
809
in step number 2 above to read as follows:
745
811
'url' => SM_PATH . 'src/options.php?optpage=plugin_demo',
747
Now, you will need to use the "optpage_set_loadinfo" hook to tell
748
SquirrelMail about your new preferences page. In setup.php in the
813
Now, you will need to use the "optpage_set_loadinfo" hook to tell
814
SquirrelMail about your new preferences page. In setup.php in the
749
815
squirrelmail_plugin_init_demo() function:
751
817
$squirrelmail_plugin_hooks['optpage_set_loadinfo']['demo']
752
818
= 'demo_optpage_loadinfo';
754
820
Assuming the function demo_optpage_loadinfo() calls another function
755
elsewhere called demo_optpage_loadinfo_do(), that function needs to
756
define values for four variables (make sure you test to see that it
821
elsewhere called demo_optpage_loadinfo_do(), that function needs to
822
define values for four variables (make sure you test to see that it
757
823
is your plugin that is being called by checking the GET variable you
758
824
added to the url just above):
760
global $optpage, $optpage_name, $optpage_file,
826
global $optpage, $optpage_name, $optpage_file,
761
827
$optpage_loader, $optpage_loadhook;
762
828
if ($optpage == 'plugin_demo')
809
875
4. Saving your options settings: if you used the second method in step
810
876
number 3 above, your settings will be saved automatically (or you can
811
define special functions to save special settings such as the
877
define special functions to save special settings such as the
812
878
save_plugin_demo_favorite_color() function in the example described
813
879
above) and there is probably no need to follow this step. If you
814
880
created your own preferences page from scratch, you'll need to follow
815
881
this step. First, you need to register your plugin against the
816
882
"options_save" hook. In setup.php in the squirrelmail_plugin_init_demo()
819
885
$squirrelmail_plugin_hooks['options_save']['demo']
820
886
= 'demo_save_options';
823
889
elsewhere called demo_save_options_do(), that function needs to grab
824
890
all of your POST and/or GET settings values and save them in the user's
825
891
preferences (for more about preferences, see that section below). Since
826
this is a generic hook called for all custom preferences pages, you
892
this is a generic hook called for all custom preferences pages, you
827
893
should always set "optpage" as a POST or GET variable with a string that
828
894
uniquely identifies your plugin:
830
<input type="hidden" name="optpage" value="plugin_demo">
896
<input type="hidden" name="optpage" value="plugin_demo" />
832
898
Now in your demo_save_options_do() function, do something like this:
837
903
sqgetGlobalVar('favorite_color', $favorite_color, SQ_FORM);
838
904
setPref($data_dir, $username, 'favorite_color', $favorite_color);
841
Note that $favorite_color may not need to be globalized, although
907
Note that $favorite_color may not need to be globalized, although
842
908
experience has shown that some versions of PHP don't behave as expected
843
909
unless you do so. Even when you use SquirrelMail's built-in preferences
844
page generation functionality, you may still use this hook, although
845
there should be no need to do so. If you need to do some complex
910
page generation functionality, you may still use this hook, although
911
there should be no need to do so. If you need to do some complex
846
912
validation routines, note that it might be better to do so in the file
847
913
you specified as the "$optpage_file" (in our example, that was the
848
plugins/demo/options.php file), since at this point, you can still
914
plugins/demo/options.php file), since at this point, you can still
849
915
redisplay your preferences page. You could put code similar to this
850
916
in the plugins/demp/options.php file (note that there is no function;
851
917
this code needs to be executed at include time):
854
if ($optmode == 'submit')
920
if ($optmode == 'submit')
856
922
// do something here such as validation, etc
857
923
if (you want to redisplay your preferences page)
877
943
setPref($data_dir, $username, 'pref_name', $pref_value);
879
945
Where "pref_name" is the key under which the value will be stored
880
and "pref_value" is a variable that should contain the actual
946
and "pref_value" is a variable that should contain the actual
881
947
preference value to be stored.
883
949
Loading preferences:
885
951
There are two approaches to retrieving plugin (or any other) preferences.
886
952
You can grab individual preferences one at a time or you can add your
887
plugin's preferences to the routine that loads up user preferences at
953
plugin's preferences to the routine that loads up user preferences at
888
954
the beginning of each page request. If you do the latter, making sure
889
955
to place your preference variables into the global scope, they will be
890
956
immediately available in all other plugin code. To retrieve a single
951
1017
So, even in the HTML segments of your plugin files, you need to do this:
953
<input type="submit" value="<?php echo _("Submit") ?>">
1019
<input type="submit" value="<?php echo _("Submit"); ?>" />
955
1021
You can put any text you want inside of the quotes (you MUST use double
956
quotes!), including HTML tags, etc. What you should think carefully
957
about is that some languages may use different word ordering, so this
1022
quotes!), including HTML tags, etc. What you should think carefully
1023
about is that some languages may use different word ordering, so this
958
1024
might be problematic:
960
1026
echo _("I want to eat a ") . $fruitName . _(" before noon");
962
1028
Because some languages (Japanese, for instance) would need to translate
963
such a sentence to "Before noon " . $fruitName . " I want to eat", but
964
with the format above, they are stuck having to translate each piece
1029
such a sentence to "Before noon " . $fruitName . " I want to eat", but
1030
with the format above, they are stuck having to translate each piece
965
1031
separately. You might want to reword your original sentence:
967
1033
echo _("This is what I want to eat before noon: ") . $fruitName;
1033
1099
-C means you are translating a file with C/C++ type syntax (ie. PHP)
1034
1100
*.php is all the files you want translations for
1036
Note, however, that this will not always pick up all strings, so you
1102
Note, however, that this will not always pick up all strings, so you
1037
1103
should double-check manually. Of course, it's easiest if you just keep
1038
1104
track of all your strings as you are coding your plugin. Your .po file
1039
1105
will now look something like:
1053
1119
"MIME-Version: 1.0\n"
1054
1120
"Content-Type: text/plain; charset=CHARSET\n"
1055
1121
"Content-Transfer-Encoding: ENCODING\n"
1057
1123
#: functions.php:45
1061
1127
#: functions.php:87
1062
1128
msgid "Favorite Color"
1065
1131
You should change the header to look something more like:
1067
# Copyright (c) 1999-2003 The Squirrelmail Development Team
1133
# Copyright (c) 1999-2005 The SquirrelMail Development Team
1068
1134
# Roland Bauerschmidt <rb@debian.org>, 1999.
1135
# $Id: plugin.txt,v 1.24.2.25 2005/01/14 06:15:22 cigamit Exp $
1071
"Project-Id-Version: $Id: squirrelmail.po,v 1.10 2003/06/04 15:01:59
1072
philippe_mingo Exp $\n"
1138
"Project-Id-Version: plugin-name version\n"
1073
1139
"POT-Creation-Date: 2003-01-21 19:21+0100\n"
1074
1140
"PO-Revision-Date: 2003-01-21 21:01+0100\n"
1075
1141
"Last-Translator: Juergen Edner <juergen.edner@epost.de>\n"
1076
"Language-Team: German <squirrelmail-i18n@lists.squirrelmail.net>\n"
1142
"Language-Team: German <squirrelmail-i18n@lists.sourceforge.net>\n"
1077
1143
"MIME-Version: 1.0\n"
1078
1144
"Content-Type: text/plain; charset=ISO-8859-1\n"
1079
1145
"Content-Transfer-Encoding: 8bit\n"
1081
1147
The most important thing to change here is the charset on the next to
1082
1148
last line. You'll want to keep a master copy of the .po file and make
1083
a copy for each language you have a translation for. You'll need to
1149
a copy for each language you have a translation for. You'll need to
1084
1150
translate each string in the .po file:
1087
1153
msgstr "Guten Tag"
1089
After you're done translating, you can create the .mo file very simply
1155
After you're done translating, you can create the .mo file very simply
1090
1156
by running the following command (available on most linux systems):
1092
1158
msgfmt -o <plugin name>.mo <plugin name>.po
1101
1167
and change your Language setting to see the translations in action!
1105
Documenting the Code (Optional)
1106
-------------------------------
1108
If you wish, you can use phpdoc (Javadoc-style) comments, when documenting your
1111
If you follow the standards that are followed between Squirrelmail core &
1112
plugin developers, the resulted documentation can be included with the rest of
1113
the Squirrelmail code & API documentation. Specifically, in the page-level
1114
docblock, declare the package to be 'plugins', and the subpackage to be the
1115
name of your plugin. For instance:
1120
* Copyright (c) 2003 My Name <my-email-address>
1121
* Licensed under the GNU GPL. For full terms see the file COPYING.
1127
The rest is up to you. Try to follow some common sense and document what is
1128
really needed. Documenting the code properly can be a big help not only to
1129
yourself, but to those who will take a look at your code, fix the bugs and even
1130
improve it, in the true open-source spirit that Squirrelmail was built upon.
1132
For more information about phpdocumentor and how to write proper-tagged
1133
comments, you are directed at:
1135
http://phpdocu.sourceforge.net/
1139
1170
PLUGIN STANDARDS AND REQUIREMENTS
1140
1171
=================================
1144
1175
small and providing the fastest webmail client on the Internet. As such,
1145
1176
we'd like it if plugin authors coded with the same goals in mind that the
1146
1177
core developers do. Common sense is always a good tool to have in your
1147
programming repertoire, but below is an outline of some standards that we
1148
ask you as a plugin developer to meet. Depending upon how far you bend
1149
these rules, we may not want to post your plugin on the SquirrelMail
1178
programming repertoire, but below is an outline of some standards that we
1179
ask you as a plugin developer to meet. Depending upon how far you bend
1180
these rules, we may not want to post your plugin on the SquirrelMail
1150
1181
website... and of course, no one really wants your efforts to go to waste
1151
1182
and for the SquirrelMail community to miss out on a potentially useful
1152
1183
plugin, so please try to follow these guidelines as closely as possible.
1178
1209
Internationalization
1179
1210
--------------------
1181
Q: What is more disappointing to users in France who would make good
1212
Q: What is more disappointing to users in France who would make good
1182
1213
use of your plugin than learning that it is written entirely in English?
1183
1214
A: Learning that they cannot send you a French translation file for your
1186
1217
There are thousands of users out there whose native tongue is not English,
1187
1218
and when you develop your plugin without going through the three simple steps
1188
needed to internationalize it, you are effectively writing them all off.
1219
needed to internationalize it, you are effectively writing them all off.
1189
1220
PLEASE consider internationalizing your plugin!
1245
1276
In order for systems administrators to keep better track of your plugin and
1246
1277
get upgrades more efficiently, you are requested to make version information
1247
available to SquirrelMail in a format that it understands. There are two
1248
ways to do this. Presently, we are asking that you do both, since we are
1249
still in a transition period between the two. This is painless, so please
1278
available to SquirrelMail in a format that it understands. There are two
1279
ways to do this. Presently, we are asking that you do both, since we are
1280
still in a transition period between the two. This is painless, so please
1250
1281
be sure to include it:
1252
1283
1. Create a file called "version" in the plugin directory. That file
1253
1284
should have only two lines: the first line should have the name of
1254
1285
the plugin as named on the SquirrelMail web site (this is often a
1255
prettified version of the plugin directory name), the second line
1286
prettified version of the plugin directory name), the second line
1256
1287
must have the version and nothing more. So for our "demo" plugin,
1257
whose name on the web site might be something like "Demo Favorite
1288
whose name on the web site might be something like "Demo Favorite
1258
1289
Colors", the file plugins/demo/version should have these two lines:
1260
1291
Demo Favorite Colors
1290
1321
In the past, there have been some rather serious issues with PHP sessions
1291
1322
and SquirrelMail, and certain people have worked long and hard to ensure
1292
1323
that these problems no longer occur in an extremely wide variety of OS/PHP/
1293
web server environments. Thus, if you need to place any values into the
1294
user's session, there are some built-in SquirrelMail functions that you are
1324
web server environments. Thus, if you need to place any values into the
1325
user's session, there are some built-in SquirrelMail functions that you are
1295
1326
strongly encouraged to make use of. Using them also makes your job easier.
1297
1328
1. To place a variable into the session:
1299
global $favorite_color;
1330
global $favorite_color;
1300
1331
$favoriteColor = 'green';
1301
1332
sqsession_register($favorite_color, 'favorite_color');
1351
1382
your plugin directory, you may copy the file there as well to be extra
1352
1383
safe. If you are storing sensitive configuration files or other data
1353
1384
in such a directory, you could even include a .htaccess file with the
1354
contents "Deny From All" that will disallow access to that directory
1385
contents "Deny From All" that will disallow access to that directory
1355
1386
entirely (when the target system is running the Apache web server).
1356
1387
Keep in mind that not all web servers will honor an .htaccess file, so
1357
1388
don't depend on it for security. Make sure not to put such a file in
1358
1389
your main plugin directory!
1360
2. A file that describes your plugin and offers detailed instructions for
1361
configuration or help with troubleshooting, etc. This file is usually
1391
2. A file that describes your plugin and offers detailed instructions for
1392
configuration or help with troubleshooting, etc. This file is usually
1362
1393
entitled "README". Some useful sections to include might be:
1364
1395
Plugin Name and Author
1387
1418
to config.php and edit config.php, making adjustments as
1388
1419
you deem necessary. For more detailed explanations about
1389
1420
each of these parameters, consult the README file.
1392
1423
$ cp config.php.sample config.php
1393
1424
$ vi config.php
1396
1427
3) Then go to your config directory and run conf.pl. Choose
1397
1428
option 8 and move the plugin from the "Available Plugins"
1398
1429
category to the "Installed Plugins" category. Save and exit.
1400
1431
$ cd ../../config/
1404
1435
Upgrading the Demo Plugin
1405
1436
=========================
1430
1461
time, especially when the new SquirrelMail version contains any architectural
1431
1462
and/or functional changes, plugin developers are put in a unique and very
1432
1463
difficult position. That is, there will be people running both the old and
1433
new versions of SquirrelMail who want to use your plugin, and you will
1464
new versions of SquirrelMail who want to use your plugin, and you will
1434
1465
probably want to accomodate them both.
1436
1467
The easiest way to keep both sides happy is to keep two different versions