[Jifty-commit] r2592 - in jifty/branches/template-declare: . debian doc doc/talks lib/Jifty lib/Jifty/Model lib/Jifty/Param lib/Jifty/Plugin/REST lib/Jifty/Script lib/Jifty/View/Static lib/Jifty/Web lib/Jifty/Web/Form share/web/templates/__jifty/admin/model t/TestApp/t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Fri Jan 26 08:30:52 EST 2007


Author: jesse
Date: Fri Jan 26 08:30:51 2007
New Revision: 2592

Added:
   jifty/branches/template-declare/doc/jifty-model-svk
   jifty/branches/template-declare/t/TestApp/t/i18n-standalone.t
Modified:
   jifty/branches/template-declare/   (props changed)
   jifty/branches/template-declare/Makefile.PL
   jifty/branches/template-declare/debian/control
   jifty/branches/template-declare/doc/talks/npw.2006.xul
   jifty/branches/template-declare/doc/talks/oscon-europe.2006.xul
   jifty/branches/template-declare/doc/talks/oscon.2006.xul
   jifty/branches/template-declare/doc/talks/yapc.na.2006.xul
   jifty/branches/template-declare/lib/Jifty/API.pm
   jifty/branches/template-declare/lib/Jifty/Continuation.pm
   jifty/branches/template-declare/lib/Jifty/DateTime.pm
   jifty/branches/template-declare/lib/Jifty/Model/Session.pm
   jifty/branches/template-declare/lib/Jifty/Param/Schema.pm
   jifty/branches/template-declare/lib/Jifty/Plugin/REST/Dispatcher.pm
   jifty/branches/template-declare/lib/Jifty/Record.pm
   jifty/branches/template-declare/lib/Jifty/Result.pm
   jifty/branches/template-declare/lib/Jifty/Script/Action.pm
   jifty/branches/template-declare/lib/Jifty/Script/FastCGI.pm
   jifty/branches/template-declare/lib/Jifty/Script/Model.pm
   jifty/branches/template-declare/lib/Jifty/Script/Po.pm
   jifty/branches/template-declare/lib/Jifty/Script/Server.pm
   jifty/branches/template-declare/lib/Jifty/Server.pm
   jifty/branches/template-declare/lib/Jifty/Util.pm
   jifty/branches/template-declare/lib/Jifty/View/Static/Handler.pm
   jifty/branches/template-declare/lib/Jifty/Web.pm
   jifty/branches/template-declare/lib/Jifty/Web/Form/Field.pm
   jifty/branches/template-declare/lib/Jifty/Web/Session.pm
   jifty/branches/template-declare/share/po/en.po
   jifty/branches/template-declare/share/po/fr.po
   jifty/branches/template-declare/share/po/ja.po
   jifty/branches/template-declare/share/po/zh_cn.po
   jifty/branches/template-declare/share/po/zh_tw.po
   jifty/branches/template-declare/share/web/templates/__jifty/admin/model/dhandler

Log:
 r21262 at hualien (orig r2542):  jesse | 2007-01-23 15:14:32 +0800
  r21255 at hualien:  jesse | 2007-01-22 23:05:46 -0800
  * Misc minor startup-time performance improvements
 
 r21268 at hualien (orig r2543):  agentz | 2007-01-23 17:57:48 +0800
 updated *.po for the recent changes in the source
 r21269 at hualien (orig r2544):  agentz | 2007-01-23 20:06:24 +0800
 [share/po]
 - s/\r\n/\n/g
 - updated zh_cn.po to use non-tw-ish chinese. :)
 r21270 at hualien (orig r2545):  agentz | 2007-01-24 15:38:33 +0800
 [Jifty::I18N]
 * added the update method which reconstructs the locale
   handle (used by Jifty::Handler::handle_request)
 * &_(loc) now uses the global locale handle instead of
   the one set up during Jifty::I18N->new().
 * Audrey's refresh method now always calls C<update>
   either directly or indirectly (via C<new>)
 [Jifty::Handler]
 * C<handle_request> now always calls
   Jifty::I18N->update directly or indirectly
   (via C<Jifty::I18N->refresh>)
 With this patch, Jifty's I18N works perfectly per
 user's HTTP request when using the standalone server
 (or possibly with Apache too)
 
 r21271 at hualien (orig r2546):  agentz | 2007-01-24 18:14:07 +0800
 [I18N]
 * fixed the _(s, ...) syntax in pony
 * updated po/*.po accordingly
 * changed fr.po to UTF-8 for consistency
 * added missing entries to zh_tw.po (yes, audreyt, i'm
   using traditional chinese this time. :))
 * changed some entries in zh_cn.po.
 r21273 at hualien (orig r2547):  agentz | 2007-01-24 18:26:57 +0800
 oops, I broke t/i18n.t. reverted two lines of code in I18N.pm.
 r21287 at hualien (orig r2548):  agentz | 2007-01-24 21:16:18 +0800
 - reverted r2545 and r2547 since i'm breaking stuff. :(
 r21288 at hualien (orig r2549):  agentz | 2007-01-24 22:21:55 +0800
 [share/po/fr.po]
 - oops, forgot to update the CHARSET header...
 r21289 at hualien (orig r2550):  trs | 2007-01-25 06:48:45 +0800
  r19045 at zot:  tom | 2007-01-24 17:48:29 -0500
  * Only allow method calls if the "field" is actually a column
  * Force stringification so that we don't segfault trying to output blessed references and what not
 
 r21302 at hualien (orig r2551):  trs | 2007-01-25 10:46:31 +0800
  r19047 at zot:  tom | 2007-01-24 21:46:07 -0500
  * Fix running actions (checking for allowed-ness was done wrong)
  * Cut down on a lot of the crap that we outputed and fix up structure
  * Make it possible to request XML from the URL like the other data formats
  * Show action params in any data format instead of just an HTML form
 
 r21303 at hualien (orig r2552):  trs | 2007-01-25 11:05:03 +0800
  r19049 at zot:  tom | 2007-01-24 22:04:51 -0500
  Show an action HTML form when rendering /=/action/App.Action.Foo as HTML
 
 r21304 at hualien (orig r2553):  trs | 2007-01-25 11:10:09 +0800
  r19051 at zot:  tom | 2007-01-24 22:10:00 -0500
  Unnecessary URL now that we special case
 
 r21305 at hualien (orig r2554):  trs | 2007-01-25 11:33:06 +0800
  r19053 at zot:  tom | 2007-01-24 22:32:57 -0500
  Make sure undefined values stay undefined and not ''
 
 r21306 at hualien (orig r2555):  trs | 2007-01-25 15:17:06 +0800
  r19057 at zot:  tom | 2007-01-25 02:16:53 -0500
  * Beginnings of help.  Of dubious location at the moment, but at least it's there.
  * Fix so both .perl and .pl work
 
 r21307 at hualien (orig r2556):  trs | 2007-01-25 15:23:56 +0800
  r19059 at zot:  tom | 2007-01-25 02:23:47 -0500
  Now with more POD!
 
 r21308 at hualien (orig r2557):  audreyt | 2007-01-25 16:11:25 +0800
 * Jifty SVK model, 0th draft
 r21310 at hualien (orig r2558):  jesse | 2007-01-25 16:38:43 +0800
  r21301 at hualien:  jesse | 2007-01-25 14:41:19 +0800
   * added a jiftyfied version if agentzh's i18n tests. I'm seeing one (french) failure
  
 
 r21312 at hualien (orig r2559):  jesse | 2007-01-25 17:58:35 +0800
  r21311 at hualien:  jesse | 2007-01-25 17:58:06 +0800
   * inital pod and sections
 
 r21323 at hualien (orig r2560):  agentz | 2007-01-25 23:21:06 +0800
 halos.css - fixed the position type for #render_info.
 IE only respects "absolute" here. No appearance changes
 for mozilla browsers.
 r21324 at hualien (orig r2561):  agentz | 2007-01-26 00:33:45 +0800
 oh no, "fixed" is not "absolute"...reverted the previous commit...
 r21329 at hualien (orig r2564):  jesse | 2007-01-26 11:55:36 +0800
  r21328 at hualien:  jesse | 2007-01-26 11:55:19 +0800
  * Allow create, load_or_create and load_by_cols to be used as class methods.
 
 r21354 at hualien (orig r2571):  audreyt | 2007-01-26 19:29:25 +0800
 * Jifty: Deprecate ->length in web form and param fields;
   write ->max_length instead.
 r21356 at hualien (orig r2573):  audreyt | 2007-01-26 19:32:07 +0800
 * s/length/max_length/ in docs/talks/.
 r21358 at hualien (orig r2575):  audreyt | 2007-01-26 19:36:48 +0800
 * Makefile.PL - Depend on Jifty::DBI 0.31 because of the
   incompatible "max_length is ..." change in schemas.
 r21364 at hualien (orig r2580):  yves | 2007-01-26 19:53:30 +0800
 debian changes for Jifty::DBI 0.31
 


Modified: jifty/branches/template-declare/Makefile.PL
==============================================================================
--- jifty/branches/template-declare/Makefile.PL	(original)
+++ jifty/branches/template-declare/Makefile.PL	Fri Jan 26 08:30:51 2007
@@ -42,7 +42,7 @@
 requires('Hash::Merge');
 requires('Hook::LexWrap');
 requires('IPC::PubSub' => '0.22' );
-requires('Jifty::DBI' => '0.30' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
+requires('Jifty::DBI' => '0.31' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
 requires('Locale::Maketext::Extract' => '0.20');
 requires('Locale::Maketext::Lexicon' => '0.60');
 requires('Log::Log4perl');

Modified: jifty/branches/template-declare/debian/control
==============================================================================
--- jifty/branches/template-declare/debian/control	(original)
+++ jifty/branches/template-declare/debian/control	Fri Jan 26 08:30:51 2007
@@ -64,7 +64,7 @@
  libhtml-lint-perl, libhtml-mason-perl (>> 1.31), 
  libwww-perl, libhttp-server-simple-perl (>> 0.26), 
  libhttp-server-simple-recorder-perl, libhash-merge-perl, libhook-lexwrap-perl,
- libipc-pubsub-perl (>> 0.22), libjifty-dbi-perl (>> 0.30),
+ libipc-pubsub-perl (>> 0.22), libjifty-dbi-perl (>> 0.31),
  liblocale-maketext-lexicon-perl, liblog-log4perl-perl,
  libmime-types-perl, libmodule-pluggable-perl (>> 3.1),
  libmodule-corelist-perl, libmodule-refresh-perl,

Added: jifty/branches/template-declare/doc/jifty-model-svk
==============================================================================
--- (empty file)
+++ jifty/branches/template-declare/doc/jifty-model-svk	Fri Jan 26 08:30:51 2007
@@ -0,0 +1,102 @@
+=head1 name
+
+Jifty SVK Model docs
+
+=head1 SUMMARY
+
+
+
+=head1 IMPLEMENTATION
+
+=head2 Reading and writing from the data store
+
+- Upon each mount, read everything, expiry-keyed by revnum
+    - Build in-memory index for common accesses
+    - Encourage ->begin and ->commit to take advantage of svk txns
+    - Otherwise it's autocommit
+        - svn:author is $ApplicationClass-$ApplicationUser
+
+=head2 Implementation plan
+
+=head3 Functionality
+
+=over
+
+=item  create objects
+
+=item  read objects
+
+=item  find objects
+
+=item  update objects
+
+=item  delete objects
+
+=back
+
+
+=head3 API
+
+- First step is a memory-only, svn-compatible layout backend store
+    - Composed of alternate implementation of APIs of:
+        - Jifty::Record
+        - Jifty::Collection
+
+
+
+
+
+=head2 Data storage format (In SVN)
+
+- Subversion based object store, using headless YAML::Syck for now
+    - Each object is a /UUID/ directory
+        - Optionally encoded as /U/UUID/ or /U/UU/UUID/ etc
+    - Each field is a /UUID/field_name file
+        - If it has a jifty:class then it's going to be blessed into that
+    - Type the object is encoded as the dirprop jifty:table
+        - It's blessed into the "class" name defined in the jifty-table repository
+    - Time of creation object is encoded as the dirprop jifty:created
+        - A simple floating number of Time::HiRes::time()
+    - The jifty:table themselves are but UUIDs of table-objects
+        - Also stored in the data store
+        - They are of the builtin table "Jifty::Model::Table"
+            - "class"   : [ "Perl::Land::Class" ]   # Record Class
+        - They are of the builtin table "Jifty::Model::Column"
+            - "table"   : the Table it's associated of
+            - "name"    : field name
+            - "type"    : jifty type-tag
+            - ...other column info...
+        - J::M::T and J::M::C (recursively defined) are always present in any data store
+        - Consequently, jifty model --create must do a uuidgen when backending SVN.
+
+
+=head3 Runtime storage format (in memory)
+
+    - In-memory structure looks like this:
+        {$type-uuid}
+            [objects-sorted-by-timestamp]
+                - inside-out objects comprised of a single UUID as payload
+        {$object-uuid}
+            - real stuff, blessed hashes of
+                field       => value-or-object
+                '.'         => UUID
+                '.created'  => timestamp
+                '.table'    => table name
+    - Column/schema info is encoded in the store itself as {$type-uuid-of-Jifty::Model::Type}{*}
+        - Introspect/modifiable as any regular model
+
+=head2 Limitations
+
+
+=head3 Runtime Typecasting
+
+my $uuid = $typed_record->id;   # concat of time and uuid
+# ...somebody retypes it and stores it...
+$typed_record->load_by_id($uuid); # oops
+
+=head3 Performance
+
+=head3 Search
+
+=head3 Scalability
+

Modified: jifty/branches/template-declare/doc/talks/npw.2006.xul
==============================================================================
Binary files. No diff available.

Modified: jifty/branches/template-declare/doc/talks/oscon-europe.2006.xul
==============================================================================
Binary files. No diff available.

Modified: jifty/branches/template-declare/doc/talks/oscon.2006.xul
==============================================================================
Binary files. No diff available.

Modified: jifty/branches/template-declare/doc/talks/yapc.na.2006.xul
==============================================================================
Binary files. No diff available.

Modified: jifty/branches/template-declare/lib/Jifty/API.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/API.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/API.pm	Fri Jan 26 08:30:51 2007
@@ -10,7 +10,7 @@
 
 =cut
 
-use Jifty::Everything;
+
 use base qw/Class::Accessor::Fast Jifty::Object/;
 
 

Modified: jifty/branches/template-declare/lib/Jifty/Continuation.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Continuation.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Continuation.pm	Fri Jan 26 08:30:51 2007
@@ -36,7 +36,7 @@
 
 =cut
 
-use Jifty::Everything;
+
 use Storable 'dclone';
 
 use base qw/Class::Accessor::Fast/;

Modified: jifty/branches/template-declare/lib/Jifty/DateTime.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/DateTime.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/DateTime.pm	Fri Jan 26 08:30:51 2007
@@ -18,7 +18,6 @@
 
 use base qw(Jifty::Object DateTime);
 
-use Date::Manip ();
 
 =head2 new ARGS
 
@@ -82,6 +81,7 @@
         
         # Why are we parsing this as GMT? This feels really wrong.  It will get the wrong answer
         # if the current user is in another tz.
+        require Date::Manip;
         Date::Manip::Date_Init("TZ=GMT");
         $now = Date::Manip::UnixDate( $string, "%o" );
     }

Modified: jifty/branches/template-declare/lib/Jifty/Model/Session.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Model/Session.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Model/Session.pm	Fri Jan 26 08:30:51 2007
@@ -30,7 +30,7 @@
 package Jifty::Model::Session;
 
 use base qw( Jifty::Record );
-use DateTime;
+use DateTime ();
 
 =head2 table
 

Modified: jifty/branches/template-declare/lib/Jifty/Param/Schema.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Param/Schema.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Param/Schema.pm	Fri Jan 26 08:30:51 2007
@@ -88,7 +88,6 @@
         valid       => 'valid_values',
         render      => 'render_as',
         order       => 'sort_order',
-        max_length  => 'length',
     },
     copula  => {
         is      => '',

Modified: jifty/branches/template-declare/lib/Jifty/Plugin/REST/Dispatcher.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Plugin/REST/Dispatcher.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Plugin/REST/Dispatcher.pm	Fri Jan 26 08:30:51 2007
@@ -12,7 +12,7 @@
 use Data::Dumper ();
 use XML::Simple;
 
-before qr{^ (/=/ .*) \. (js|json|yml|yaml|perl|pl) $}x => run {
+before qr{^ (/=/ .*) \. (js|json|yml|yaml|perl|pl|xml) $}x => run {
     $ENV{HTTP_ACCEPT} = $2;
     dispatch $1;
 };
@@ -22,27 +22,88 @@
     dispatch $1;
 };
 
-on GET    '/=/model/*/*/*/*' => \&show_item_field;
-on GET    '/=/model/*/*/*'   => \&show_item;
-on GET    '/=/model/*/*'     => \&list_model_items;
-on GET    '/=/model/*'       => \&list_model_columns;
-on GET    '/=/model'         => \&list_models;
-
-on PUT    '/=/model/*/*/*' => \&replace_item;
-on DELETE '/=/model/*/*/*' => \&delete_item;
-
-on GET    '/=/action/*'    => \&list_action_params;
-on GET    '/=/action'      => \&list_actions;
-on POST   '/=/action/*'    => \&run_action;
+on GET    '/=/model/*/*/*/*'    => \&show_item_field;
+on GET    '/=/model/*/*/*'      => \&show_item;
+on GET    '/=/model/*/*'        => \&list_model_items;
+on GET    '/=/model/*'          => \&list_model_columns;
+on GET    '/=/model'            => \&list_models;
 
+on PUT    '/=/model/*/*/*'      => \&replace_item;
+on DELETE '/=/model/*/*/*'      => \&delete_item;
 
-=head2 list PREFIX items
+on GET    '/=/action/*'         => \&list_action_params;
+on GET    '/=/action'           => \&list_actions;
+on POST   '/=/action/*'         => \&run_action;
+
+on GET    '/=/help'             => \&show_help;
+
+=head2 show_help
+
+Shows basic help about resources and formats available via this RESTian interface.
+
+=cut
+
+sub show_help {
+    my $apache = Jifty->handler->apache;
+
+    $apache->header_out('Content-Type' => 'text/plain; charset=UTF-8');
+    $apache->send_http_header;
+   
+    print qq{
+Accessing resources:
+
+on GET    /=/model                                  list models
+on GET    /=/model/<model>                          list model columns
+on GET    /=/model/<model>/<column>                 list model items
+on GET    /=/model/<model>/<column>/<key>           show item
+on GET    /=/model/<model>/<column>/<key>/<field>   show item field
+
+on PUT    /=/model/<model>/<column>/<key>           replace item -- UNIMPLEMENTED!
+on DELETE /=/model/<model>/<column>/<key>           delete item -- UNIMPLEMENTED!
+
+on GET    /=/action                                 list actions
+on GET    /=/action/<action>                        list action params
+on POST   /=/action/<action>                        run action
+
+Note that the PUT and DELETE methods on models are essentially available through
+Update<Model> and Delete<Model> actions.
 
-Takes a URL prefix and a set of items to render. passes them on.
+
+Resources are available in a variety of formats:
+
+    JSON, JS, YAML, XML, Perl, and HTML
+
+and may be requested in such formats by sending an appropriate HTTP Accept: header
+or appending one of the extensions to any resource:
+
+    .json, .js, .yaml, .xml, .pl
+
+HTML is output only if the Accept: header or an extension does not request a
+specific format.
+    };
+    last_rule;
+}
+
+
+=head2 stringify LIST
+
+Takes a list of values and forces them into strings.  Right now all it does
+is concatenate them to an empty string, but future versions might be more
+magical.
 
 =cut
 
+sub stringify {
+    no warnings 'uninitialized';
+    my @r = map { defined $_ ? '' . $_ : undef } @_;
+    return wantarray ? @r : pop @r;
+}
 
+=head2 list PREFIX items
+
+Takes a URL prefix and a set of items to render. passes them on.
+
+=cut
 
 sub list {
     my $prefix = shift;
@@ -88,7 +149,7 @@
         $apache->send_http_header;
         print 'var $_ = ', Jifty::JSON::objToJson( @_, { singlequote => 1 } );
     }
-    elsif ($accept =~ /perl/i) {
+    elsif ($accept =~ qr{^(?:application/x-)?(?:perl|pl)$}i) {
         $apache->header_out('Content-Type' => 'application/x-perl; charset=UTF-8');
         $apache->send_http_header;
         print Data::Dumper::Dumper(@_);
@@ -101,14 +162,22 @@
     else {
         $apache->header_out('Content-Type' => 'text/html; charset=UTF-8');
         $apache->send_http_header;
-        print render_as_html($prefix, $url, @_);
+        
+        # Special case showing particular actions to show an HTML form
+        if ( $prefix->[0] eq 'action' and scalar @$prefix == 2 ) {
+            show_action_form($1);
+        }
+        else {
+            print render_as_html($prefix, $url, @_);
+        }
     }
 
     last_rule;
 }
 
-our $xml_config = { SuppressEmpty => '',
-                    NoAttr => 1 };
+our $xml_config = { SuppressEmpty   => '',
+                    NoAttr          => 1,
+                    RootName        => 'data' };
 
 =head2 render_as_xml DATASTRUCTURE
 
@@ -125,7 +194,7 @@
     elsif (ref($content) eq 'HASH') {
         return XMLout($content, %$xml_config);
     } else {
-        return XMLout({$content}, %$xml_config)
+        return XMLout({value => $content}, %$xml_config)
     }
 }
 
@@ -250,26 +319,22 @@
 =cut
 
 sub list_models {
-    list(['model'], map {s/::/./g; $_ } Jifty->class_loader->models);
+    list(['model'], map { s/::/./g; $_ } Jifty->class_loader->models);
 }
 
 our @column_attrs = 
-qw(    name
+qw( name
     type
     default
-    validator
     readable writable
     length
     mandatory
-    virtual
     distinct
     sort_order
-    refers_to by
+    refers_to
     alias_for_column
     aliased_as
-    since until
-
-    label hints render_as
+    label hints
     valid_values
 );
 
@@ -285,14 +350,16 @@
     my ($model) = model($1);
 
     my %cols;
-    map {
-            my $col = $_;
-            $cols{$col->name} = { map { $_ => $col->$_() } @column_attrs} ;
-    } $model->new->columns;
-
-    outs(
-        [ 'model', $model ], \%cols
-    );
+    for my $col ( $model->new->columns ) {
+        $cols{ $col->name } = { };
+        for ( @column_attrs ) {
+            my $val = $col->$_();
+            $cols{ $col->name }->{ $_ } = $val
+                if defined $val and length $val;
+        }
+    }
+
+    outs( [ 'model', $model ], \%cols );
 }
 
 =head2 list_model_items MODELCLASS COLUMNNAME
@@ -303,16 +370,17 @@
 
 
 sub list_model_items {
-
     # Normalize model name - fun!
     my ( $model, $column ) = ( model($1), $2 );
     my $col = $model->new->collection_class->new;
     $col->unlimit;
-    $col->columns($column);
+
+    # If we don't load the PK, we won't get data
+    $col->columns("id", $column);
     $col->order_by( column => $column );
 
     list( [ 'model', $model, $column ],
-        map { $_->$column() } @{ $col->items_array_ref || [] } );
+        map { stringify($_->$column()) } @{ $col->items_array_ref || [] } );
 }
 
 
@@ -321,8 +389,6 @@
 Loads up a model of type C<$model> which has a column C<$column> with a value C<$key>. Returns the value of C<$field> for that object. 
 Returns 404 if it doesn't exist.
 
-
-
 =cut
 
 sub show_item_field {
@@ -331,7 +397,11 @@
     $rec->load_by_cols( $column => $key );
     $rec->id          or abort(404);
     $rec->can($field) or abort(404);
-    outs( [ 'model', $model, $column, $key, $field ], $rec->$field());
+
+    # Check that the field is actually a column (and not some other method)
+    abort(404) if not scalar grep { $_->name eq $field } $rec->columns;
+
+    outs( [ 'model', $model, $column, $key, $field ], stringify($rec->$field()) );
 }
 
 =head2 show_item $model, $column, $key
@@ -347,7 +417,7 @@
     my $rec = $model->new;
     $rec->load_by_cols( $column => $key );
     $rec->id or abort(404);
-    outs( ['model', $model, $column, $key],  { map {$_ => $rec->$_()} map {$_->name} $rec->columns});
+    outs( ['model', $model, $column, $key],  { map {$_ => stringify($rec->$_())} map {$_->name} $rec->columns});
 }
 
 
@@ -385,12 +455,49 @@
 
 Takes a single parameter, $action, supplied by the dispatcher.
 
-Shows the user all possible parameters to the action, currently in the form of a form to run that action.
+Shows the user all possible parameters to the action.
 
 =cut
 
+our @param_attrs = qw(
+    name
+    type
+    default_value
+    label
+    hints
+    mandatory
+    length
+);
+
 sub list_action_params {
-    my ($action) = action($1) or abort(404);
+    my ($class) = action($1) or abort(404);
+    Jifty::Util->require($class) or abort(404);
+    my $action = $class->new or abort(404);
+
+    my $arguments = $action->arguments;
+    my %args;
+    for my $arg ( keys %$arguments ) {
+        $args{ $arg } = { };
+        for ( @param_attrs ) {
+            my $val = $arguments->{ $arg }{ $_ };
+            $args{ $arg }->{ $_ } = $val
+                if defined $val and length $val;
+        }
+    }
+
+    outs( ['action', $class], \%args );
+}
+
+=head2 show_action_form $ACTION_CLASS
+
+Takes a single parameter, the class of an action.
+
+Shows the user an HTML form of the action's parameters to run that action.
+
+=cut
+
+sub show_action_form {
+    my ($action) = action(shift) or abort(404);
     Jifty::Util->require($action) or abort(404);
     $action = $action->new or abort(404);
 
@@ -435,7 +542,7 @@
     Jifty::Util->require($action_name) or abort(404);
     my $action = $action_name->new or abort(404);
 
-    Jifty->api->is_allowed( $action ) or abort(403);
+    Jifty->api->is_allowed( $action_name ) or abort(403);
 
     my $args = Jifty->web->request->arguments;
     delete $args->{''};

Modified: jifty/branches/template-declare/lib/Jifty/Record.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Record.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Record.pm	Fri Jan 26 08:30:51 2007
@@ -32,6 +32,7 @@
 
 =head2 create PARAMHASH
 
+C<create> can be called as either a class method or an object method.
 
 Takes an array of key-value pairs and inserts a new row into the database representing
 this object.
@@ -51,7 +52,14 @@
 =cut 
 
 sub create {
-    my $self    = shift;
+    my $class    = shift;
+    my $self;
+    if (ref($class)) { 
+        ($self,$class) = ($class,undef);
+    } else {
+        $self = $class->new();
+    }
+
     my %attribs = @_;
 
     unless ( $self->check_create_rights(@_) ) {
@@ -73,7 +81,11 @@
         my ( $val, $msg ) = $func->($self, $attr);
         unless ($val) {
             $self->log->error("There was a validation error for $key");
-            return ( $val, $msg );
+            if ($class) {
+                return($self);
+            } else {
+                return ( $val, $msg );
+            }
         }
         }
         # remove blank values. We'd rather have nulls
@@ -90,7 +102,11 @@
     }
     my ($id, $status) = $msg;
     $self->load_by_cols( id => $id ) if ($id);
-    return wantarray ? ($id, $status) : $id;
+    if ($class) {
+        return $self;
+    } else {
+        return wantarray ? ($id, $status) : $id;
+    }
 }
 
 
@@ -107,13 +123,21 @@
 
 =head2 load_or_create
 
-Attempts to load a record with the named parameters passed in.  If it
+C<load_or_create> can be called as either a class method or an object method.
+It attempts to load a record with the named parameters passed in.  If it
 can't do so, it creates a new record.
 
 =cut
 
 sub load_or_create {
-    my $self = shift;
+    my $class = shift;
+    my $self;
+    if (ref($class)) {
+       ($self,$class) = ($class,undef); 
+    } else {
+        $self = $class->new();
+    }
+
     my %args = (@_);
 
     my ( $id, $msg ) = $self->load_by_cols(%args);

Modified: jifty/branches/template-declare/lib/Jifty/Result.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Result.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Result.pm	Fri Jan 26 08:30:51 2007
@@ -15,7 +15,7 @@
 
 =cut
 
-use Jifty::Everything;
+
 
 use base qw/Jifty::Object Class::Accessor::Fast/;
 

Modified: jifty/branches/template-declare/lib/Jifty/Script/Action.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Script/Action.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Script/Action.pm	Fri Jan 26 08:30:51 2007
@@ -4,7 +4,7 @@
 package Jifty::Script::Action;
 use base qw/App::CLI::Command/;
 
-use Jifty::Everything;
+
 
 =head1 NAME
 

Modified: jifty/branches/template-declare/lib/Jifty/Script/FastCGI.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Script/FastCGI.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Script/FastCGI.pm	Fri Jan 26 08:30:51 2007
@@ -7,7 +7,7 @@
 
 use File::Basename;
 use CGI::Fast;
-use Jifty::Everything;
+
 
 =head1 NAME
 

Modified: jifty/branches/template-declare/lib/Jifty/Script/Model.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Script/Model.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Script/Model.pm	Fri Jan 26 08:30:51 2007
@@ -4,7 +4,7 @@
 package Jifty::Script::Model;
 use base qw/App::CLI::Command/;
 
-use Jifty::Everything;
+
 
 =head1 NAME
 

Modified: jifty/branches/template-declare/lib/Jifty/Script/Po.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Script/Po.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Script/Po.pm	Fri Jan 26 08:30:51 2007
@@ -4,12 +4,12 @@
 package Jifty::Script::Po;
 use base qw(App::CLI::Command Class::Accessor::Fast);
 
-use File::Copy;
-use Jifty::Config;
-use Jifty::YAML;
-use Locale::Maketext::Extract;
-use File::Find::Rule;
-use MIME::Types;
+use File::Copy ();
+use Jifty::Config ();
+use Jifty::YAML ();
+use Locale::Maketext::Extract ();
+use File::Find::Rule ();
+use MIME::Types ();
 our $MIME = MIME::Types->new();
 our $LMExtract = Locale::Maketext::Extract->new;
 use constant USE_GETTEXT_STYLE => 1;

Modified: jifty/branches/template-declare/lib/Jifty/Script/Server.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Script/Server.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Script/Server.pm	Fri Jan 26 08:30:51 2007
@@ -17,7 +17,7 @@
 BEGIN { $SIG{__DIE__} = $x;}
 
 
-use Jifty::Everything;
+
 use File::Path ();
 
 use constant PIDFILE => 'var/jifty-server.pid';

Modified: jifty/branches/template-declare/lib/Jifty/Server.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Server.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Server.pm	Fri Jan 26 08:30:51 2007
@@ -20,7 +20,7 @@
 
 =cut
 
-use Jifty::Everything;
+
 use base qw/HTTP::Server::Simple::CGI/;
 use base qw/Jifty::Object/;
 use File::Spec;

Modified: jifty/branches/template-declare/lib/Jifty/Util.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Util.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Util.pm	Fri Jan 26 08:30:51 2007
@@ -12,16 +12,10 @@
 
 =cut
 
-use Jifty;
-use File::Spec;
-use File::Path;
-use File::ShareDir;
-use UNIVERSAL::require;
-use ExtUtils::MakeMaker ();
+use Jifty ();
+use File::Spec ();
 use Cwd ();
-use Config;
 
-# Trivial memoization to ward off evil Cwd calls.
 use vars qw/%ABSOLUTE_PATH $JIFTY_ROOT $SHARE_ROOT $APP_ROOT/;
 
 
@@ -107,6 +101,8 @@
 sub share_root {
     my $self = shift;
 
+    
+    Jifty::Util->require('File::ShareDir');
     $SHARE_ROOT ||=  eval { File::Spec->rel2abs( File::ShareDir::module_dir('Jifty') )};
     if (not $SHARE_ROOT or not -d $SHARE_ROOT) {
         # XXX TODO: This is a bloody hack
@@ -141,14 +137,14 @@
 
     push( @roots, Cwd::cwd() );
 
-    eval { require FindBin };
+    eval { Jifty::Util->require('FindBin') };
     if ( my $err = $@ ) {
-
         #warn $@;
     } else {
         push @roots, $FindBin::Bin;
     }
 
+    Jifty::Util->require('Config');
     for (@roots) {
         my @root = File::Spec->splitdir($_);
         while (@root) {
@@ -161,8 +157,8 @@
                 # %Config{bin} or %Config{scriptdir} or something like that
                 # for portablility.
                 (-e $try or (($^O =~ /(?:MSWin32|cygwin|os2)/) and MM->maybe_command($try)))
-                and $try ne File::Spec->catdir($Config{bin}, "jifty")
-                and $try ne File::Spec->catdir($Config{scriptdir}, "jifty") )
+                and $try ne File::Spec->catdir($Config::Config{bin}, "jifty")
+                and $try ne File::Spec->catdir($Config::Config{scriptdir}, "jifty") )
             {
                 return $APP_ROOT = File::Spec->catdir(@root);
             }
@@ -207,6 +203,7 @@
     my $self = shift;
     my $whole_path = shift;
     return 1 if (-d $whole_path);
+    Jifty::Util->require('File::Path');
     File::Path::mkpath([$whole_path]);
 }
 

Modified: jifty/branches/template-declare/lib/Jifty/View/Static/Handler.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/View/Static/Handler.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/View/Static/Handler.pm	Fri Jan 26 08:30:51 2007
@@ -10,8 +10,7 @@
 
 use base qw/Jifty::Object/;
 
-our $mime  = MIME::Types->new();
-our $magic = File::MMagic->new();
+our ($MIME,$MAGIC);
 
 =head1 NAME
 
@@ -160,12 +159,11 @@
     return ($type_override{$1})
         if $local_path =~ /\.(.+)$/ and defined $type_override{$1};
 
-    my $mimeobj   = $mime->mimeTypeOf($local_path);
-    my $mime_type = (
-          $mimeobj
-        ? $mimeobj->type
-        : $magic->checktype_filename($local_path)
-    );
+    # Defer initialization to first use. (It's not actually cheap)
+    $MIME ||= MIME::Types->new();
+    $MAGIC ||= File::MMagic->new();
+    my $mimeobj   = $MIME->mimeTypeOf($local_path);
+    my $mime_type = ( $mimeobj ? $mimeobj->type : $MAGIC->checktype_filename($local_path));
 
     return ($mime_type);
 }

Modified: jifty/branches/template-declare/lib/Jifty/Web.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Web.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Web.pm	Fri Jan 26 08:30:51 2007
@@ -11,7 +11,7 @@
 
 
 
-use Jifty::Everything;
+
 use CGI::Cookie;
 use XML::Writer;
 use CSS::Squish;

Modified: jifty/branches/template-declare/lib/Jifty/Web/Form/Field.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Web/Form/Field.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Web/Form/Field.pm	Fri Jan 26 08:30:51 2007
@@ -13,7 +13,7 @@
 label
 hints
 placeholder
-length
+max_length
 mandatory
 
 =end properties
@@ -104,8 +104,8 @@
 
 =cut
 
-sub accessors { shift->SUPER::accessors(), qw(name label input_name type sticky sticky_value default_value action mandatory ajax_validates ajax_canonicalizes autocompleter preamble hints placeholder focus render_mode length _element_id disable_autocomplete); }
-__PACKAGE__->mk_accessors(qw(name _label _input_name type sticky sticky_value default_value _action mandatory ajax_validates ajax_canonicalizes autocompleter preamble hints placeholder focus render_mode length _element_id disable_autocomplete));
+sub accessors { shift->SUPER::accessors(), qw(name label input_name type sticky sticky_value default_value action mandatory ajax_validates ajax_canonicalizes autocompleter preamble hints placeholder focus render_mode max_length _element_id disable_autocomplete); }
+__PACKAGE__->mk_accessors(qw(name _label _input_name type sticky sticky_value default_value _action mandatory ajax_validates ajax_canonicalizes autocompleter preamble hints placeholder focus render_mode max_length _element_id disable_autocomplete));
 
 =head2 name [VALUE]
 
@@ -489,7 +489,7 @@
     $field .= qq! id="@{[ $self->element_id ]}"!;
     $field .= qq! value="@{[Jifty->web->escape($self->current_value)]}"! if defined $self->current_value;
     $field .= $self->_widget_class; 
-    $field .= qq! size="@{[ $self->length() ]}" maxlength="@{[ $self->length() ]}"! if ($self->length());
+    $field .= qq! size="@{[ $self->max_length() ]}" maxlength="@{[ $self->length() ]}"! if ($self->max_length());
     $field .= qq! autocomplete="off"! if defined $self->disable_autocomplete;
     $field .= " " .$self->other_widget_properties;
     $field .= qq!  />\n!;
@@ -711,4 +711,13 @@
     return '';
 }
 
+
+# Deprecated API
+sub length {
+    my $self = shift;
+    Carp::carp("->length is deprecated; use ->max_length instead");
+    $self->max_length(@_);
+}
+
+
 1;

Modified: jifty/branches/template-declare/lib/Jifty/Web/Session.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/Web/Session.pm	(original)
+++ jifty/branches/template-declare/lib/Jifty/Web/Session.pm	Fri Jan 26 08:30:51 2007
@@ -3,9 +3,9 @@
 
 package Jifty::Web::Session;
 use base qw/Jifty::Object/;
-use CGI::Cookie;
-use DateTime;
-
+use CGI::Cookie ();
+use DateTime ();
+ 
 =head1 NAME
 
 Jifty::Web::Session - A Jifty session handler

Modified: jifty/branches/template-declare/share/po/en.po
==============================================================================
--- jifty/branches/template-declare/share/po/en.po	(original)
+++ jifty/branches/template-declare/share/po/en.po	Fri Jan 26 08:30:51 2007
@@ -94,7 +94,7 @@
 msgid "(any)"
 msgstr ""
 
-#: lib/Jifty/Web/Form/Field.pm:521
+#: lib/Jifty/Web/Form/Field.pm:549
 msgid "@{[$self->current_value]}"
 msgstr ""
 
@@ -118,7 +118,7 @@
 msgid "Any field contains"
 msgstr ""
 
-#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:20
+#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:21
 msgid "Back to the admin console"
 msgstr ""
 
@@ -168,6 +168,10 @@
 msgid "Deleted"
 msgstr ""
 
+#: share/web/templates/__jifty/admin/index.html:28 share/web/templates/__jifty/admin/model/dhandler:20
+msgid "Done?"
+msgstr ""
+
 #: share/web/templates/__jifty/admin/fragments/list/view:40
 msgid "Edit"
 msgstr ""
@@ -186,6 +190,10 @@
 msgid "Hiya, %1."
 msgstr ""
 
+#: share/web/templates/__jifty/admin/index.html:1
+msgid "Jifty Administrative Console"
+msgstr ""
+
 #: share/web/templates/__jifty/online_docs/toc.html:6
 msgid "Jifty Developer Documentation Online"
 msgstr ""
@@ -198,6 +206,15 @@
 msgid "Loading..."
 msgstr ""
 
+#: share/web/templates/__jifty/admin/model/dhandler:9
+#. ($object_type)
+msgid "Manage %1 records"
+msgstr ""
+
+#: share/web/templates/__jifty/admin/model/dhandler:11
+msgid "Manage records:"
+msgstr ""
+
 #: share/web/templates/__jifty/error/mason_internal_error:1
 msgid "Mason error"
 msgstr ""
@@ -218,7 +235,7 @@
 msgid "No items found"
 msgstr ""
 
-#: lib/Jifty/Web.pm:297
+#: lib/Jifty/Web.pm:299
 msgid "No request to handle"
 msgstr ""
 
@@ -267,19 +284,19 @@
 msgid "Table of Contents"
 msgstr ""
 
-#: lib/Jifty/Action.pm:873
+#: lib/Jifty/Action.pm:876
 msgid "That doesn't look like a correct value"
 msgstr ""
 
-#: lib/Jifty/Action/Record.pm:247
+#: lib/Jifty/Action/Record.pm:248
 msgid "That doesn't look right, but I don't know why"
 msgstr ""
 
-#: lib/Jifty/Action/Record.pm:179
+#: lib/Jifty/Action/Record.pm:180
 msgid "The passwords you typed didn't match each other"
 msgstr ""
 
-#: lib/Jifty/Web.pm:360
+#: lib/Jifty/Web.pm:362
 msgid "There was an error completing the request.  Please try again later."
 msgstr ""
 
@@ -311,7 +328,7 @@
 msgid "You got to a page that we don't think exists.  Anyway, the software has logged this error. Sorry about this."
 msgstr ""
 
-#: lib/Jifty/Action.pm:860
+#: lib/Jifty/Action.pm:863
 msgid "You need to fill in this field"
 msgstr ""
 

Modified: jifty/branches/template-declare/share/po/fr.po
==============================================================================
--- jifty/branches/template-declare/share/po/fr.po	(original)
+++ jifty/branches/template-declare/share/po/fr.po	Fri Jan 26 08:30:51 2007
@@ -12,17 +12,17 @@
 "Last-Translator: AGOSTINI Yves <agostini at univ-metz.fr>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO8859-15\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
 #: lib/Jifty/Action/Record/Search.pm:125
 msgid "!=>< allowed"
-msgstr "!=>< autorisés"
+msgstr "!=>< autorisés"
 
 #: lib/Jifty/Action/Record/Search.pm:115
 #. ($label)
 msgid "%1 after"
-msgstr "%1 aprés"
+msgstr "%1 aprés"
 
 #: lib/Jifty/Action/Record/Search.pm:116
 #. ($label)
@@ -42,12 +42,12 @@
 #: lib/Jifty/Action/Record/Search.pm:123
 #. ($label)
 msgid "%1 greater or equal to"
-msgstr "%1 supérieur ou égal à"
+msgstr "%1 supérieur ou égal à"
 
 #: lib/Jifty/Action/Record/Search.pm:121
 #. ($label)
 msgid "%1 greater than"
-msgstr "%1 supérieur à"
+msgstr "%1 supérieur à"
 
 #: lib/Jifty/Action/Record/Search.pm:108
 #. ($label)
@@ -62,12 +62,12 @@
 #: lib/Jifty/Action/Record/Search.pm:124
 #. ($label)
 msgid "%1 less or equal to"
-msgstr "%1 inférieur ou égal"
+msgstr "%1 inférieur ou égal"
 
 #: lib/Jifty/Action/Record/Search.pm:122
 #. ($label)
 msgid "%1 less than"
-msgstr "%1 inférieur à"
+msgstr "%1 inférieur à"
 
 #: share/web/templates/__jifty/error/mason_internal_error:31 share/web/templates/__jifty/error/mason_internal_error:35 share/web/templates/__jifty/error/mason_internal_error:39
 #. ($path, $line)
@@ -94,7 +94,7 @@
 msgid "(any)"
 msgstr ""
 
-#: lib/Jifty/Web/Form/Field.pm:521
+#: lib/Jifty/Web/Form/Field.pm:549
 msgid "@{[$self->current_value]}"
 msgstr ""
 
@@ -104,7 +104,7 @@
 
 #: share/web/templates/_elements/wrapper:11
 msgid "Administration mode is enabled."
-msgstr "Mode d'administration activé."
+msgstr "Mode d'administration activé."
 
 #: share/web/templates/_elements/wrapper:11
 msgid "Alert"
@@ -112,19 +112,19 @@
 
 #: lib/Jifty/Action/Record/Create.pm:82
 msgid "An error occurred.  Try again later"
-msgstr "Erreur. Ré-essayez plus tard"
+msgstr "Erreur. Ré-essayez plus tard"
 
 #: lib/Jifty/Action/Record/Search.pm:129
 msgid "Any field contains"
 msgstr "Un champs contient"
 
-#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:20
+#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:21
 msgid "Back to the admin console"
-msgstr "Retour à l'interface d'admin"
+msgstr "Retour à l'interface d'admin"
 
 #: share/web/templates/__jifty/admin/index.html:29
 msgid "Back to the application"
-msgstr "Retour à l'application"
+msgstr "Retour à l'application"
 
 #: share/web/templates/helpers/calendar.html:4
 #. (_ &><body class="calpopup"><a href="#" onclick="window.close()
@@ -137,7 +137,7 @@
 
 #: share/web/templates/helpers/calendar.html:4
 msgid "Close window"
-msgstr "Fermer la fenêtre"
+msgstr "Fermer la fenêtre"
 
 #: share/web/templates/__jifty/admin/fragments/list/view:31
 msgid "Confirm delete?"
@@ -150,15 +150,15 @@
 #: lib/Jifty/Action/Record/Create.pm:81
 #. (ref($record)
 msgid "Create of %1 failed: %2"
-msgstr "La création de %1 a échoué: %2"
+msgstr "La création de %1 a échoué: %2"
 
 #: lib/Jifty/Action/Record/Create.pm:105
 msgid "Created"
-msgstr "Créé"
+msgstr "Créé"
 
 #: share/web/templates/__jifty/admin/index.html:3
 msgid "Database Administration"
-msgstr "Administration de la Base de Données"
+msgstr "Administration de la Base de Données"
 
 #: share/web/templates/__jifty/admin/fragments/list/view:29
 msgid "Delete"
@@ -166,7 +166,11 @@
 
 #: lib/Jifty/Action/Record/Delete.pm:76
 msgid "Deleted"
-msgstr "Effacé"
+msgstr "Effacé"
+
+#: share/web/templates/__jifty/admin/index.html:28 share/web/templates/__jifty/admin/model/dhandler:20
+msgid "Done?"
+msgstr ""
 
 #: share/web/templates/__jifty/admin/fragments/list/view:40
 msgid "Edit"
@@ -186,6 +190,10 @@
 msgid "Hiya, %1."
 msgstr "Bonjour, %1"
 
+#: share/web/templates/__jifty/admin/index.html:1
+msgid "Jifty Administrative Console"
+msgstr ""
+
 #: share/web/templates/__jifty/online_docs/toc.html:6
 msgid "Jifty Developer Documentation Online"
 msgstr ""
@@ -198,13 +206,22 @@
 msgid "Loading..."
 msgstr "Chargement..."
 
+#: share/web/templates/__jifty/admin/model/dhandler:9
+#. ($object_type)
+msgid "Manage %1 records"
+msgstr ""
+
+#: share/web/templates/__jifty/admin/model/dhandler:11
+msgid "Manage records:"
+msgstr ""
+
 #: share/web/templates/__jifty/error/mason_internal_error:1
 msgid "Mason error"
 msgstr "Erreur Mason"
 
 #: share/web/templates/__jifty/admin/index.html:9
 msgid "Models"
-msgstr "Modèles"
+msgstr "Modèles"
 
 #: share/web/templates/__jifty/admin/fragments/list/list:113
 msgid "Next Page"
@@ -218,9 +235,9 @@
 msgid "No items found"
 msgstr "Aucun enregistrement"
 
-#: lib/Jifty/Web.pm:297
+#: lib/Jifty/Web.pm:299
 msgid "No request to handle"
-msgstr "Aucune requête à traiter"
+msgstr "Aucune requête à traiter"
 
 #: share/web/templates/__jifty/online_docs/index.html:5
 msgid "Online Documentation"
@@ -233,19 +250,19 @@
 
 #: lib/Jifty/Record.pm:240 lib/Jifty/Record.pm:319 lib/Jifty/Record.pm:60
 msgid "Permission denied"
-msgstr "Autorisation refusée"
+msgstr "Autorisation refusée"
 
 #: share/web/templates/__jifty/admin/fragments/list/list:108
 msgid "Previous Page"
-msgstr "Page précédente"
+msgstr "Page précédente"
 
 #:
 msgid "Record created"
-msgstr "Enregistrement créé"
+msgstr "Enregistrement créé"
 
 #: share/web/templates/__jifty/admin/action/dhandler:20
 msgid "Run the action"
-msgstr "Exécuter l'action"
+msgstr "Exécuter l'action"
 
 #: share/web/templates/__jifty/halo:111
 msgid "SQL Statements"
@@ -257,7 +274,7 @@
 
 #: share/web/templates/__jifty/online_docs/content.html:50
 msgid "Schema"
-msgstr "Schéma"
+msgstr "Schéma"
 
 #: share/web/templates/__jifty/admin/fragments/list/search:18
 msgid "Search"
@@ -265,35 +282,35 @@
 
 #: share/web/templates/dhandler:1
 msgid "Something's not quite right"
-msgstr "Problème"
+msgstr "Problème"
 
 #: share/web/templates/__jifty/online_docs/index.html:16 share/web/templates/__jifty/online_docs/index.html:18
 msgid "Table of Contents"
-msgstr "Table des matières"
+msgstr "Table des matières"
 
-#: lib/Jifty/Action.pm:873
+#: lib/Jifty/Action.pm:876
 msgid "That doesn't look like a correct value"
 msgstr "Valeur incorecte"
 
-#: lib/Jifty/Action/Record.pm:247
+#: lib/Jifty/Action/Record.pm:248
 msgid "That doesn't look right, but I don't know why"
-msgstr "Problème"
+msgstr "Problème"
 
-#: lib/Jifty/Action/Record.pm:179
+#: lib/Jifty/Action/Record.pm:180
 msgid "The passwords you typed didn't match each other"
-msgstr "Les mots de passe tapés ne sont pas identiques"
+msgstr "Les mots de passe tapés ne sont pas identiques"
 
-#: lib/Jifty/Web.pm:360
+#: lib/Jifty/Web.pm:362
 msgid "There was an error completing the request.  Please try again later."
-msgstr "Problème lors de l'exécution de cette requête. Ré-essayez plus tard."
+msgstr "Problème lors de l'exécution de cette requête. Ré-essayez plus tard."
 
 #: share/web/templates/__jifty/admin/index.html:5
 msgid "This console lets you manage the records in your Jifty database. Below, you should see a list of all your database tables. Feel free to go through and add, delete or modify records."
-msgstr "Cette page vous permet de gérer vos enregistrements dans la base. Vous trouverez ci-dessous la listes des tables. Vous pouvez ajouter, effacer ou modifier les enregistements."
+msgstr "Cette page vous permet de gérer vos enregistrements dans la base. Vous trouverez ci-dessous la listes des tables. Vous pouvez ajouter, effacer ou modifier les enregistements."
 
 #: share/web/templates/__jifty/admin/index.html:7
 msgid "To disable this administrative console, add \"AdminMode: 0\" under the \"framework:\" settings in the config file (etc/config.yml)."
-msgstr "Pour désactiver cette console d'administration, ajoutez \"AdminMode: 0\" dans la rubrique \"framework:\" du fichier de configuration (etc/config.yml)."
+msgstr "Pour désactiver cette console d'administration, ajoutez \"AdminMode: 0\" dans la rubrique \"framework:\" du fichier de configuration (etc/config.yml)."
 
 #: share/web/templates/__jifty/admin/fragments/list/list:72
 msgid "Toggle search"
@@ -301,7 +318,7 @@
 
 #: share/web/templates/__jifty/error/mason_internal_error:6
 msgid "Try again"
-msgstr "Ré-essayer"
+msgstr "Ré-essayer"
 
 #: lib/Jifty/Action/Record/Update.pm:156
 msgid "Updated"
@@ -315,7 +332,7 @@
 msgid "You got to a page that we don't think exists.  Anyway, the software has logged this error. Sorry about this."
 msgstr "Cette page n'existe pas."
 
-#: lib/Jifty/Action.pm:860
+#: lib/Jifty/Action.pm:863
 msgid "You need to fill in this field"
 msgstr "Information obligatoire"
 
@@ -326,7 +343,7 @@
 
 #: share/web/templates/_elements/sidebar:7
 msgid "You're not currently signed in."
-msgstr "Vous n'êtes pas encore connecté."
+msgstr "Vous n'êtes pas encore connecté."
 
 #: share/web/templates/__jifty/admin/fragments/list/header:22
 msgid "asc"

Modified: jifty/branches/template-declare/share/po/ja.po
==============================================================================
--- jifty/branches/template-declare/share/po/ja.po	(original)
+++ jifty/branches/template-declare/share/po/ja.po	Fri Jan 26 08:30:51 2007
@@ -94,7 +94,7 @@
 msgid "(any)"
 msgstr "(指定なし)"
 
-#: lib/Jifty/Web/Form/Field.pm:521
+#: lib/Jifty/Web/Form/Field.pm:549
 msgid "@{[$self->current_value]}"
 msgstr ""
 
@@ -118,7 +118,7 @@
 msgid "Any field contains"
 msgstr "検索したい文字列"
 
-#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:20
+#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:21
 msgid "Back to the admin console"
 msgstr "管理画面に戻る"
 
@@ -168,6 +168,10 @@
 msgid "Deleted"
 msgstr "削除しました"
 
+#: share/web/templates/__jifty/admin/index.html:28 share/web/templates/__jifty/admin/model/dhandler:20
+msgid "Done?"
+msgstr ""
+
 #: share/web/templates/__jifty/admin/fragments/list/view:40
 msgid "Edit"
 msgstr "編集"
@@ -186,6 +190,10 @@
 msgid "Hiya, %1."
 msgstr "%1 さん、こんにちは"
 
+#: share/web/templates/__jifty/admin/index.html:1
+msgid "Jifty Administrative Console"
+msgstr ""
+
 #: share/web/templates/__jifty/online_docs/toc.html:6
 msgid "Jifty Developer Documentation Online"
 msgstr "開発者向けオンラインドキュメント"
@@ -198,6 +206,15 @@
 msgid "Loading..."
 msgstr "読込み中…"
 
+#: share/web/templates/__jifty/admin/model/dhandler:9
+#. ($object_type)
+msgid "Manage %1 records"
+msgstr ""
+
+#: share/web/templates/__jifty/admin/model/dhandler:11
+msgid "Manage records:"
+msgstr ""
+
 #: share/web/templates/__jifty/error/mason_internal_error:1
 msgid "Mason error"
 msgstr "Mason エラー"
@@ -218,7 +235,7 @@
 msgid "No items found"
 msgstr "見つかりませんでした"
 
-#: lib/Jifty/Web.pm:297
+#: lib/Jifty/Web.pm:299
 msgid "No request to handle"
 msgstr "処理できるリクエストがありません"
 
@@ -267,19 +284,19 @@
 msgid "Table of Contents"
 msgstr "目次"
 
-#: lib/Jifty/Action.pm:873
+#: lib/Jifty/Action.pm:876
 msgid "That doesn't look like a correct value"
 msgstr "値が不適切なようです"
 
-#: lib/Jifty/Action/Record.pm:246
+#: lib/Jifty/Action/Record.pm:248
 msgid "That doesn't look right, but I don't know why"
 msgstr "原因不明のエラーです"
 
-#: lib/Jifty/Action/Record.pm:178
+#: lib/Jifty/Action/Record.pm:180
 msgid "The passwords you typed didn't match each other"
 msgstr "パスワードが一致しません"
 
-#: lib/Jifty/Web.pm:360
+#: lib/Jifty/Web.pm:362
 msgid "There was an error completing the request.  Please try again later."
 msgstr "リクエストの処理中にエラーが発生しました。しばらく待ってから再度試してみてください"
 
@@ -311,7 +328,7 @@
 msgid "You got to a page that we don't think exists.  Anyway, the software has logged this error. Sorry about this."
 msgstr "このページは存在しません。エラーとして記録しておきました。ご不便をお詫びいたします"
 
-#: lib/Jifty/Action.pm:860
+#: lib/Jifty/Action.pm:863
 msgid "You need to fill in this field"
 msgstr "必須項目です"
 

Modified: jifty/branches/template-declare/share/po/zh_cn.po
==============================================================================
--- jifty/branches/template-declare/share/po/zh_cn.po	(original)
+++ jifty/branches/template-declare/share/po/zh_cn.po	Fri Jan 26 08:30:51 2007
@@ -7,9 +7,9 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: Audrey Tang <audreyt at audreyt.org>\n"
-"Language-Team: Traditional Chinese\n"
+"PO-Revision-Date: 2007-01-23 16:55+08\n"
+"Last-Translator: Agent Zhang <agentzh at gmail.com>\n"
+"Language-Team: Simplified Chinese\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -36,7 +36,7 @@
 #: share/web/templates/__jifty/admin/fragments/list/list:87
 #. ($collection-> count)
 msgid "%1 entries"
-msgstr ""
+msgstr "%1 条记录"
 
 #: lib/Jifty/Action/Record/Search.pm:123
 #. ($label)
@@ -72,7 +72,7 @@
 #. ($path, $line)
 #. ($file, $line)
 msgid "%1 line %2"
-msgstr "%1 第 %2 列"
+msgstr "%1 第 %2 行"
 
 #: share/web/templates/__jifty/halo:119
 #. ($_->[3])
@@ -91,9 +91,9 @@
 
 #: lib/Jifty/Action/Record/Search.pm:77
 msgid "(any)"
-msgstr "(不限)"
+msgstr "(任意)"
 
-#: lib/Jifty/Web/Form/Field.pm:521
+#: lib/Jifty/Web/Form/Field.pm:549
 msgid "@{[$self->current_value]}"
 msgstr ""
 
@@ -117,7 +117,7 @@
 msgid "Any field contains"
 msgstr "任意字段包含"
 
-#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:20
+#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:21
 msgid "Back to the admin console"
 msgstr "回到管理界面"
 
@@ -140,11 +140,11 @@
 
 #: share/web/templates/__jifty/admin/fragments/list/view:31
 msgid "Confirm delete?"
-msgstr "确定要删除?"
+msgstr "确实要删除吗?"
 
 #: share/web/templates/__jifty/admin/fragments/list/new_item:25
 msgid "Create"
-msgstr "建立"
+msgstr "创建"
 
 #: lib/Jifty/Action/Record/Create.pm:81
 #. (ref($record)
@@ -171,6 +171,10 @@
 msgid "Dismiss"
 msgstr "关闭"
 
+#: share/web/templates/__jifty/admin/index.html:28 share/web/templates/__jifty/admin/model/dhandler:20
+msgid "Done?"
+msgstr "已完成?"
+
 #: share/web/templates/__jifty/admin/fragments/list/view:40
 msgid "Edit"
 msgstr "编辑"
@@ -182,24 +186,37 @@
 
 #: share/web/templates/dhandler:7
 msgid "Go back home..."
-msgstr "回首页..."
+msgstr "回到首页..."
 
 #: share/web/templates/_elements/sidebar:5
 #. ($u->$method()
 msgid "Hiya, %1."
-msgstr "%1 您好."
+msgstr "您好,%1。"
+
+#: share/web/templates/__jifty/admin/index.html:1
+msgid "Jifty Administrative Console"
+msgstr "Jifty 管理界面"
 
 #: share/web/templates/__jifty/online_docs/toc.html:6
 msgid "Jifty Developer Documentation Online"
-msgstr "Jifty 线上开发文件"
+msgstr "Jifty 在线开发文档"
 
 #: share/web/templates/__jifty/online_docs/content.html:6
 msgid "Jifty Pod Online"
-msgstr "Jifty 线上 POD 文件"
+msgstr "Jifty 在线 POD 文件"
 
 #: share/web/templates/_elements/wrapper:18
 msgid "Loading..."
-msgstr "请稍候..."
+msgstr "正在加载..."
+
+#: share/web/templates/__jifty/admin/model/dhandler:9
+#. ($object_type)
+msgid "Manage %1 records"
+msgstr "管理 %1 记录"
+
+#: share/web/templates/__jifty/admin/model/dhandler:11
+msgid "Manage records:"
+msgstr "管理记录:"
 
 #: share/web/templates/__jifty/error/mason_internal_error:1
 msgid "Mason error"
@@ -219,11 +236,11 @@
 
 #: share/web/templates/__jifty/admin/fragments/list/list:85
 msgid "No items found"
-msgstr ""
+msgstr "未找到记录"
 
-#: lib/Jifty/Web.pm:297
+#: lib/Jifty/Web.pm:299
 msgid "No request to handle"
-msgstr "没有可处理的要求"
+msgstr "没有可处理的请求"
 
 #: share/web/templates/__jifty/online_docs/index.html:5
 msgid "Online Documentation"
@@ -236,7 +253,7 @@
 
 #: lib/Jifty/Record.pm:240 lib/Jifty/Record.pm:319 lib/Jifty/Record.pm:60
 msgid "Permission denied"
-msgstr "权限不足."
+msgstr "权限不足"
 
 #: share/web/templates/__jifty/admin/fragments/list/list:108
 msgid "Previous Page"
@@ -244,7 +261,7 @@
 
 #:
 msgid "Record created"
-msgstr "成功建立项目."
+msgstr "成功建立记录."
 
 #: share/web/templates/__jifty/admin/action/dhandler:20
 msgid "Run the action"
@@ -256,15 +273,15 @@
 
 #: share/web/templates/__jifty/admin/fragments/list/update:21
 msgid "Save"
-msgstr "储存"
+msgstr "保存"
 
 #: share/web/templates/__jifty/online_docs/content.html:50
 msgid "Schema"
-msgstr "纲要"
+msgstr "模式"
 
 #: share/web/templates/__jifty/admin/fragments/list/search:18
 msgid "Search"
-msgstr "搜寻"
+msgstr "查找"
 
 #: share/web/templates/dhandler:1
 msgid "Something's not quite right"
@@ -274,19 +291,19 @@
 msgid "Table of Contents"
 msgstr "目录"
 
-#: lib/Jifty/Action.pm:873
+#: lib/Jifty/Action.pm:876
 msgid "That doesn't look like a correct value"
 msgstr "字段格式错误."
 
-#: lib/Jifty/Action/Record.pm:247
+#: lib/Jifty/Action/Record.pm:248
 msgid "That doesn't look right, but I don't know why"
 msgstr "字段内容错误."
 
-#: lib/Jifty/Action/Record.pm:179
+#: lib/Jifty/Action/Record.pm:180
 msgid "The passwords you typed didn't match each other"
-msgstr "两组口令不符合."
+msgstr "两组口令不匹配."
 
-#: lib/Jifty/Web.pm:360
+#: lib/Jifty/Web.pm:362
 msgid "There was an error completing the request.  Please try again later."
 msgstr "系统执行错误, 请稍候再试."
 
@@ -296,7 +313,7 @@
 
 #: share/web/templates/__jifty/admin/index.html:7
 msgid "To disable this administrative console, add \"AdminMode: 0\" under the \"framework:\" settings in the config file (etc/config.yml)."
-msgstr "如欲停用管理界面, 请在设定档 (etc/config.yml) 的 \"framework:\" 设定内加上 \"AdminMode: 0\" 即可."
+msgstr "如果想停用管理界面, 请在配置文件 (etc/config.yml) 的 \"framework:\" 配置项内加上 \"AdminMode: 0\" 即可."
 
 #: share/web/templates/__jifty/admin/fragments/list/list:72
 msgid "Toggle search"
@@ -304,7 +321,7 @@
 
 #: share/web/templates/__jifty/error/mason_internal_error:6
 msgid "Try again"
-msgstr "再试一下"
+msgstr "重试一下"
 
 #: lib/Jifty/Action/Record/Update.pm:156
 msgid "Updated"
@@ -312,15 +329,15 @@
 
 #: share/web/templates/index.html:1
 msgid "Welcome to your new Jifty application"
-msgstr "欢迎光临您崭新的 Jifty 应用程序"
+msgstr "欢迎光临您的崭新的 Jifty 应用程序"
 
 #: share/web/templates/dhandler:5
 msgid "You got to a page that we don't think exists.  Anyway, the software has logged this error. Sorry about this."
 msgstr "抱歉, 此页面不存在, 系统已留下纪录."
 
-#: lib/Jifty/Action.pm:860
+#: lib/Jifty/Action.pm:863
 msgid "You need to fill in this field"
-msgstr "此字段不能留空."
+msgstr "此字段非空."
 
 #: share/web/templates/index.html:3
 #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461')
@@ -329,12 +346,12 @@
 
 #: share/web/templates/_elements/sidebar:7
 msgid "You're not currently signed in."
-msgstr "您目前尚未登入."
+msgstr "您目前尚未登录."
 
 #: share/web/templates/__jifty/admin/fragments/list/header:22
 msgid "asc"
-msgstr ""
+msgstr "升序"
 
 #: share/web/templates/__jifty/admin/fragments/list/header:41
 msgid "desc"
-msgstr ""
+msgstr "降序"

Modified: jifty/branches/template-declare/share/po/zh_tw.po
==============================================================================
--- jifty/branches/template-declare/share/po/zh_tw.po	(original)
+++ jifty/branches/template-declare/share/po/zh_tw.po	Fri Jan 26 08:30:51 2007
@@ -93,7 +93,7 @@
 msgid "(any)"
 msgstr "(不限)"
 
-#: lib/Jifty/Web/Form/Field.pm:521
+#: lib/Jifty/Web/Form/Field.pm:549
 msgid "@{[$self->current_value]}"
 msgstr ""
 
@@ -117,7 +117,7 @@
 msgid "Any field contains"
 msgstr "任意欄位包含"
 
-#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:20
+#: share/web/templates/__jifty/admin/action/dhandler:25 share/web/templates/__jifty/admin/model/dhandler:21
 msgid "Back to the admin console"
 msgstr "回到管理界面"
 
@@ -171,6 +171,10 @@
 msgid "Dismiss"
 msgstr "關閉"
 
+#: share/web/templates/__jifty/admin/index.html:28 share/web/templates/__jifty/admin/model/dhandler:20
+msgid "Done?"
+msgstr "已完成?"
+
 #: share/web/templates/__jifty/admin/fragments/list/view:40
 msgid "Edit"
 msgstr "編輯"
@@ -189,6 +193,10 @@
 msgid "Hiya, %1."
 msgstr "%1 您好."
 
+#: share/web/templates/__jifty/admin/index.html:1
+msgid "Jifty Administrative Console"
+msgstr "Jifty 管理介面"
+
 #: share/web/templates/__jifty/online_docs/toc.html:6
 msgid "Jifty Developer Documentation Online"
 msgstr "Jifty 線上開發文件"
@@ -201,6 +209,15 @@
 msgid "Loading..."
 msgstr "請稍候..."
 
+#: share/web/templates/__jifty/admin/model/dhandler:9
+#. ($object_type)
+msgid "Manage %1 records"
+msgstr "管理 %1 記錄"
+
+#: share/web/templates/__jifty/admin/model/dhandler:11
+msgid "Manage records:"
+msgstr "管理記錄:"
+
 #: share/web/templates/__jifty/error/mason_internal_error:1
 msgid "Mason error"
 msgstr "Mason 系統錯誤"
@@ -219,9 +236,9 @@
 
 #: share/web/templates/__jifty/admin/fragments/list/list:85
 msgid "No items found"
-msgstr ""
+msgstr "未找到記錄"
 
-#: lib/Jifty/Web.pm:297
+#: lib/Jifty/Web.pm:299
 msgid "No request to handle"
 msgstr "沒有可處理的要求"
 
@@ -274,19 +291,19 @@
 msgid "Table of Contents"
 msgstr "目錄"
 
-#: lib/Jifty/Action.pm:873
+#: lib/Jifty/Action.pm:876
 msgid "That doesn't look like a correct value"
 msgstr "欄位格式錯誤."
 
-#: lib/Jifty/Action/Record.pm:247
+#: lib/Jifty/Action/Record.pm:248
 msgid "That doesn't look right, but I don't know why"
 msgstr "欄位內容錯誤."
 
-#: lib/Jifty/Action/Record.pm:179
+#: lib/Jifty/Action/Record.pm:180
 msgid "The passwords you typed didn't match each other"
 msgstr "兩組密碼不符合."
 
-#: lib/Jifty/Web.pm:360
+#: lib/Jifty/Web.pm:362
 msgid "There was an error completing the request.  Please try again later."
 msgstr "系統執行錯誤, 請稍候再試."
 
@@ -318,7 +335,7 @@
 msgid "You got to a page that we don't think exists.  Anyway, the software has logged this error. Sorry about this."
 msgstr "抱歉, 此頁面不存在, 系統已留下紀錄."
 
-#: lib/Jifty/Action.pm:860
+#: lib/Jifty/Action.pm:863
 msgid "You need to fill in this field"
 msgstr "此欄位不能留空."
 
@@ -333,8 +350,8 @@
 
 #: share/web/templates/__jifty/admin/fragments/list/header:22
 msgid "asc"
-msgstr ""
+msgstr "昇冪"
 
 #: share/web/templates/__jifty/admin/fragments/list/header:41
 msgid "desc"
-msgstr ""
+msgstr "降冪"

Modified: jifty/branches/template-declare/share/web/templates/__jifty/admin/model/dhandler
==============================================================================
--- jifty/branches/template-declare/share/web/templates/__jifty/admin/model/dhandler	(original)
+++ jifty/branches/template-declare/share/web/templates/__jifty/admin/model/dhandler	Fri Jan 26 08:30:51 2007
@@ -6,7 +6,7 @@
 $records->unlimit;
 </%init>
 
-<&| /_elements/wrapper, title => _("Manage $object_type records") &>
+<&| /_elements/wrapper, title => _("Manage %1 records", $object_type) &>
 
 <h1><% _('Manage records:') %> <%$object_type%></h1>
 

Added: jifty/branches/template-declare/t/TestApp/t/i18n-standalone.t
==============================================================================
--- (empty file)
+++ jifty/branches/template-declare/t/TestApp/t/i18n-standalone.t	Fri Jan 26 08:30:51 2007
@@ -0,0 +1,59 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+use lib 't/lib';
+use Jifty::SubTest;
+
+use Jifty::Test tests => 12;
+use Jifty::Test::WWW::Mechanize;
+use Net::HTTP;
+use URI;
+
+use Encode 'decode';
+use utf8;
+use LWP::UserAgent;
+my $server  = Jifty::Test->make_server;
+
+isa_ok($server, 'Jifty::Server');
+
+my $base = URI->new($server->started_ok);
+
+
+my $ua = LWP::UserAgent->new;
+my $res;
+
+$ua->default_header('Accept-Language' => "en");
+$res = $ua->get("$base/__jifty/admin/");
+ok $res->is_success, "can access admin console";
+like $res->content, qr/Models/, 'en works';
+
+$ua->default_header('Accept-Language' => "ja");
+$res = $ua->get("$base/__jifty/admin/");
+ok $res->is_success, "can access admin console";
+like adjust($res->content), qr/モデル/, 'ja works';
+
+$ua->default_header('Accept-Language' => "fr");
+$res = $ua->get("$base/__jifty/admin/");
+ok $res->is_success, "can access admin console";
+like adjust($res->content), qr/Modèles/, 'fr locale works';
+
+$ua->default_header('Accept-Language' => "zh-cn");
+$res = $ua->get("$base/__jifty/admin/");
+ok $res->is_success, "can access admin console";
+like adjust($res->content), qr/数据库/, 'zh-cn works';
+
+$ua->default_header('Accept-Language' => "zh-tw");
+$res = $ua->get("$base/__jifty/admin/");
+ok $res->is_success, "can access admin console";
+like adjust($res->content), qr/資料庫/, 'zh-tw works';
+
+sub adjust {
+    my $s = shift;
+    $s = decode('UTF-8', $s);
+    $s =~ s/<.*?>//gs;
+    $s =~ s/\s+/ /gs;
+    #$s =~ s/\W+//g;
+    #$s =~ s/\d+//g;
+    $s;
+}


More information about the Jifty-commit mailing list