CallBackery

 view release on metacpan or  search on metacpan

CHANGES  view on Meta::CPAN

0.29.3 2020-02-28 09:57:50 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - do not translate empty strings

0.29.2 2020-02-27 14:14:03 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - fix popup instanciation with new YAML config

0.29.1 2020-02-21 16:55:09 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - callbackery.locale.MTranslation was missing from MANIFEST and
   thus from distro

0.29.0 2020-02-21 15:37:33 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - trm with placeholder and arguments work now trm('Hello %1',$name)
 - in qooxdoo frontend code, use this.xtr(backendData) to translate
   backend data.
 * make sure to update your makefile according to the sample in
   mojolicious-automake to get xgettext support for extracting
   translatable strings

CHANGES  view on Meta::CPAN

* 4878b5b - (tag: v0.13.0) Fighting circular references (9 months ago) <Tobias Oetiker>
* 7547c30 - update PERL_MODULES (10 months ago) <Tobias Oetiker>
* 7d871b9 - (tag: v0.12.9) fix deprecated route syuntax (no more braces) (10 months ago) <Tobias Oetiker>
* d22bf7e - update template PERL_MODULES (10 months ago) <Tobias Oetiker>
* 36e18d1 - (tag: v0.12.8) updated dependncy to require latest qooxdoo plugin (10 months ago) <Tobias Oetiker>
* 71ba760 - widen tests (10 months ago) <Tobias Oetiker>
* 33507d2 - fix cpanmin.us link (10 months ago) <Tobias Oetiker>
* 1716124 - Update README.md (10 months ago) <Tobias Oetiker>
* 3cda105 - Update README.md (10 months ago) <Tobias Oetiker>
* b6b2deb - (tag: v0.12.7) search templates in templates/system (11 months ago) <Tobias Oetiker>
* 1253847 - (tag: v0.12.6) localize $_ before loading locales since this function modifies $_ (11 months ago) <Tobias Oetiker>
* aa50217 - simplify table change detection (12 months ago) <Tobias Oetiker>
* dc13afc - (tag: v0.12.5) new String is not a good thing ... stick with just String (1 year ago) <Tobias Oetiker>
* e65abe4 - add missing Makefile (1 year ago) <Tobias Oetiker>
* b0ff480 - (tag: v0.12.3) fix user object for up and downloads (1 year, 1 month ago) <Tobias Oetiker>
* 88ba138 - (tag: v0.12.2) auto build source version (1 year, 1 month ago) <Tobias Oetiker>
* 5898387 - add a cache-control header for all requests but those going for the resource files. (1 year, 1 month ago) <Tobias Oetiker>
* bd53c60 - (tag: v0.12.0) v0.12.0 (1 year, 2 months ago) <Tobias Oetiker>
* 4e0dfba - additional types supported for table columns: - string - number   including format option (1 year, 2 months ago) <Tobias Oetiker>
* 8d5425f - qxclass changes (1 year, 2 months ago) <Tobias Oetiker>
* 6494665 - local class (1 year, 2 months ago) <Tobias Oetiker>

MANIFEST  view on Meta::CPAN

lib/CallBackery.pm
lib/CallBackery/qooxdoo/callbackery/config.json
lib/CallBackery/qooxdoo/callbackery/Manifest.json
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/Application.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Config.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/__init__.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/MHistoryRelaxedEncoding.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/RemoteTableModel.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Server.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/__init__.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/locale/MTranslation.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/test/DemoTest.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/theme/Appearance.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/theme/Color.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/theme/Decoration.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/theme/Font.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/theme/Theme.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Busy.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Card.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Desktop.js
lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Footer.js

lib/CallBackery.pm  view on Meta::CPAN


=head1 DESCRIPTION

Configure the mojo engine to run our application logic as webrequests arrive.

=head1 ATTRIBUTES

=cut

# load the two modules to have perl check them
# having a non-C locale for number will wreck all sorts of havoc
# when things get converted to string and back
use POSIX qw(locale_h);
setlocale(LC_NUMERIC, "C");
setlocale(LC_TIME, "C");

use Mojo::Base 'Mojolicious';
use Mojolicious::Plugin::Qooxdoo;
use Mojo::URL;
use Mojo::JSON;
use Mojo::Util qw(hmac_sha1_sum);
use Mojo::File qw(path);
use File::Basename;
use CallBackery::Config;
use CallBackery::Plugin::Doc;

lib/CallBackery.pm  view on Meta::CPAN

=cut

=head2 startup

Mojolicious calls the startup method at initialization time.

=cut

sub startup {
    my $app = shift;
    # having a non-C locale for number will wreck all sorts of havoc
    # when things get converted to string and back
    setlocale(LC_NUMERIC, "C");
    setlocale(LC_TIME, "C");
    weaken($app);
    $app->config->postProcessCfg();
    my $gcfg = $app->config->cfgHash->{BACKEND};
    if ($gcfg->{log_file}){
        if (open my $file, '>>', $gcfg->{log_file}){
           $app->log->handle($file);
        }
        else {
           $app->log->debug("Opening $gcfg->{log_file}: $!");
        }

lib/CallBackery/Config.pm  view on Meta::CPAN


=cut

sub getTranslations {
    my $self = shift;
    my $cfg = shift || {};
    my %lx;
    my $path = $cfg->{path} // $self->app->home->rel_file("share");
    my $po = new Locale::PO();
    for my $file (glob(File::Spec->catdir($path, '*.po'))) {
        my ($volume, $localePath, $localeName) = File::Spec->splitpath($file);
        my $locale = $localeName;
        $locale =~ s/\.po$//;
        my $lang = $locale;
        $lang =~ s/_.+//;
        local $_; # since load_file_ashash modifies $_ and does not localize it
        my $href = Locale::PO->load_file_ashash($file, 'utf8');
        for my $key (keys %$href) {
            my $o = $href->{$key};
            my $id  = $po->dequote($o->msgid);
            my $str = $po->dequote($o->msgstr);
            next unless $id;
            $lx{$locale}{$id} = $str;
        }
    }
    return \%lx;
}

=head2 postProcessCfg

Post process the configuration data into a format that is easily used
by the application.

lib/CallBackery/GuiPlugin/AbstractTable.pm  view on Meta::CPAN

            my $self = shift;
            my $args = shift;
            my $data = $self->getTableData({
                formData => $args,
                firstRow => 0,
                lastRow => $self->getTableRowCount({ formData=>$args })
            });

            # Use the (translated) table headers in row 1.
            # Or the keys if undefined.
            my $loc = CallBackery::Translate->new(localeRoot=>$self->app->home->child("share"));
            $loc->setLocale($self->user->userInfo->{lang} // 'en');
            my $tCfg = $self->tableCfg;

            my @titles = map {
                $_->{label}
                    ? ((ref $_->{label} eq 'CallBackery::Translate')
                        ? $loc->tra($_->{label}[0])
                        : $_->{label})
                    : $_->{key};
            } @$tCfg;

lib/CallBackery/Translate.pm  view on Meta::CPAN

@EXPORT_OK = qw(trm);


=head1 NAME

CallBackery::Translate - gettext po file translation functionality

=head1 SYNOPSIS

 use CallBackery::Translate qw(mtr);
 my $loc = CallBackery::Translate->new(localeRoot=>$dir);
 $loc->setLocale('de');
 $loc->tra("Hello %1","Tobi");

 trm("Mark but for translation but return original");

=head1 DESCRIPTION

Read translations from gettext po files and translate incoming data.

=cut

has 'localeRoot';

=over

=item C<setLocale>($locale);

Load the translations strings for $locale. First try the full name and
then top-up with only the language part.

=cut

my %lx;

sub setLocale {
    my $self = shift;
    my $locale = shift;
    if ($lx{$locale}){
        $self->{_lx} = $lx{$locale};
        return;
    }
    my $lang = $locale;
    $lang =~ s/_.+//;
    for my $file ($lang,$locale){
        my $mode = 'id';
        if (open my $fh, '< :encoding(utf8)', $self->localeRoot.'/'.$file.'.po'){
            my $key;
            my %var;
            while (<$fh>){
                chomp;
                /^msg(id|str)\s+"(.*)"/ && do {
                    $var{$1} = $2;
                    $key = $1;
                    next;
                };
                /^"(.*)"/ && do {
                    $var{$key} .= $1;
                    next;
                };
                /^\s*$/ && $var{id} && do {
                    $lx{$locale}{$var{id}} = $var{str};
                    next;
                }
            }
            $lx{$locale}{$var{id}} = $var{str} if $var{id} and $var{str};
        }
    }
    $self->{_lx} = $lx{$locale};
}

=item C<tra>(str[,arg,arg,...])

Translate string into the curent language.

=cut

sub tra {
    my $self = shift;

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/Application.js  view on Meta::CPAN

    */

    members : {

        main : function() {
            // Call super class
            this.base(arguments);
            // include the xtr call so that we can use frontend translation
            // on backend strings.
            qx.Class.patch(qx.ui.table.columnmodel.Resize,
                callbackery.locale.MTranslation);
            qx.Class.patch(qx.ui.core.Widget,
                    callbackery.locale.MTranslation);
            // Enable logging in debug variant
            if (qx.core.Environment.get("qx.debug")) {
                // support native logging capabilities, e.g. Firebug for Firefox
                qx.log.appender.Native;
                // support additional cross-browser console. Press F7 to toggle visibility
                qx.log.appender.Console;
            }
            var rpc = callbackery.data.Server.getInstance();
            var root = this.getRoot();
            root.set({

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/Application.js  view on Meta::CPAN

            /* give the History object a more relaxed attitude towards encoding stuff */
            qx.Class.patch(qx.bom.History,callbackery.data.MHistoryRelaxedEncoding);
            qx.bom.History.getInstance().addListener('changeState', this.__changeLanguage, this);
            this.__changeLanguage();

            rpc.callAsyncSmart(function(baseCfg){
                var cfg = callbackery.data.Config.getInstance();
                cfg.setBaseConfig(baseCfg);
                if (baseCfg.TRANSLATIONS){
                    var t = baseCfg.TRANSLATIONS;
                    var lm = qx.locale.Manager.getInstance();
                    for (var lang in t) {
                        lm.addTranslation(lang, t[lang]);
                    }
                }
                if (baseCfg.COLORS){
                    qx.Theme.define('callbackery.theme.CustomColor',{
                        colors: baseCfg.COLORS
                    });
                    var colorTheme = qx.theme.manager.Color.getInstance().getTheme();
                    qx.Theme.patch(colorTheme,callbackery.theme.CustomColor);

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/Application.js  view on Meta::CPAN


        },

        registerPlugin: function(type, func) {
            return callbackery.ui.Plugins.getInstance().register(type, func);
        },

        __changeLanguage: function() {
            var urlCfg = callbackery.data.Config.getInstance().getUrlConfig();
            if (urlCfg.lang) {
                qx.locale.Manager.getInstance().setLocale(urlCfg.lang);
            }
        },

        getFooterWidget : function() {
            return callbackery.ui.Footer.getInstance();
        },

        getHeaderWidget : function() {
            return callbackery.ui.Header.getInstance();
        }

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/RemoteTableModel.js  view on Meta::CPAN

   Utf8Check:  äöü

************************************************************************ */

/**
 * An {@link qx.ui.table.model.Remote} implementation for accessing
 * accessing Messreihen on the server.
 */
qx.Class.define('callbackery.data.RemoteTableModel', {
    extend: qx.ui.table.model.Remote,
    include: [callbackery.locale.MTranslation],
    /**
     * Create an instance of Rpc.
     */
    construct: function(cfg, getParentFormData) {
        this.base(arguments);
        this._getParentFormData = getParentFormData;
        var that = this;
        var ids = [];
        var labels = [];
        var types = {};

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Server.js  view on Meta::CPAN

         * @return {var} the method call reference.
         */
        callAsync: function(handler, methodName) {
            if (methodName == 'login'){
                // arguments.callee.base.apply(this, arguments);
                arguments.callee.base.apply(this, arguments);
                return;
            }
            var origArguments = arguments;
            var origThis = this;
            var localeMgr = qx.locale.Manager.getInstance();
            var newArgs = Array.prototype.slice.call(arguments);
            newArgs[0] = function(ret, exc, id) {
                if (exc) {
                    switch (exc.code) {
                        case 6:
                            let login = callbackery.ui.Login.getInstance();
                            login.addListenerOnce('login', (e) => {
                                let ret = e.getData();
                                origThis.setSessionCookie(ret.sessionCookie);
                                origArguments.callee.base.apply(origThis, origArguments);

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Server.js  view on Meta::CPAN

                try {
                  handler(ret, exc, id);
                }
                catch(e) {
                    if (window.console){
                        window.console.error("Error while running CallAsync Handler","ret:",ret,"exc",exc,"id",id,"e",e);
                    }
                }
            };
            newArgs.push({
                qxLocale: localeMgr.getLocale()
            });
            arguments.callee.base.apply(this, newArgs);
        },
        /**
         * A variant of the asyncCall method which pops up error messages
         * generated by the server automatically.
         *
         * Note that the handler method only gets a return value never an exception
         * It just does not get called when there is an exception.
         *

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/locale/MTranslation.js  view on Meta::CPAN

/* *************************************************
   Copyright: 2019 OETIKER+PARTNER AG
   License: GNU GPL 3
   Authors: Tobias Oetiker <tobi@oetiker.ch>
************************************************** */

/**
 * Translation helper which can process backend translatable objects
 */

qx.Mixin.define("callbackery.locale.MTranslation", {

    members: {
        /**
         * override the regular tr with this magic version which is able to handle
         * data coming in from the backend. This is for backward compatibility.
         * Better use the xtr call as this will not trigger the translation
         * string extraction.
         */
        tr: function() {
            return this.xtr.apply(this,arguments);
        },
        /**
         * Translate incoming data. Do NOT mark the string for translation
         * use the tr function for this. xtr is meant for backend strings.
         */
        xtr: function(messageId,varargs) {
            var nlsManager = qx.locale.Manager;
            if (messageId == ''){
                return '';
            }
            if (messageId instanceof Array) {
                return nlsManager.tr.apply(nlsManager, messageId);
            }
            if (messageId instanceof qx.data.Array) {
                return nlsManager.tr.apply(nlsManager, messageId.toArray());
            }
            return nlsManager.tr.apply(nlsManager, arguments);

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

//      dateField.setTextSelection(0,0);
    }, this);

    this.addListener("focusout", function(e) {
      dateField.fireNonBubblingEvent("focusout", qx.event.type.Focus);
    }, this);

    // initializes the DateField with the default format
    this._setDefaultDateFormat();

    // adds a locale change listener
    this._addLocaleChangeListener();
  },




  /*
  *****************************************************************************
     EVENTS
  *****************************************************************************

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

    __dateFormat : null,
    __formatter : null,

    /**
     * Get the shared default date formatter
     *
     * @return {qx.util.format.DateFormat} The shared date formatter
     */
    getDefaultDateFormatter : function()
    {
      var format = qx.locale.Date.getDateFormat("medium").toString();

      if (format == this.__dateFormat) {
        return this.__formatter;
      }

      if (this.__formatter) {
        this.__formatter.dispose();
      }

      this.__formatter = new qx.util.format.DateFormat(format, qx.locale.Manager.getInstance().getLocale());
      this.__dateFormat = format;

      return this.__formatter;
    }
  },




  /*
  *****************************************************************************
     MEMBERS
  *****************************************************************************
  */

  members :
  {
    __localeListenerId : null,


    /**
     * @lint ignoreReferenceField(_forwardStates)
     */
    _forwardStates : {
      focused : true,
      invalid : true
    },

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

     * Sets the default date format which is returned by
     * {@link #getDefaultDateFormatter}. You can overrride this method to
     * define your own default format.
     */
    _setDefaultDateFormat : function() {
      this.setDateFormat(qx.ui.form.DateField.getDefaultDateFormatter());
    },


    /**
     * Checks for "qx.dynlocale" and adds a listener to the locale changes.
     * On every change, {@link #_setDefaultDateFormat} is called to reinitialize
     * the format. You can easily override that method to prevent that behavior.
     */
    _addLocaleChangeListener : function() {
      // listen for locale changes
      if (qx.core.Environment.get("qx.dynlocale"))
      {
        this.__localeListenerId =
          qx.locale.Manager.getInstance().addListener("changeLocale", function() {
            this._setDefaultDateFormat();
          }, this);
      }
    },


    /*
    ---------------------------------------------------------------------------
      PUBLIC METHODS
    ---------------------------------------------------------------------------

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

      }
      catch (ex) {
        // do nothing if the former date could not be parsed
      }
    },


    // property apply routine
    _applyPlaceholder : function(value, old) {
        var p = value.split("@");
//        this.getChildControl("datefield").setPlaceholder(qx.locale.Manager.tr(p[0]));
        this.getChildControl("datefield").setPlaceholder(this.xtr(p[0]));
        if (p[1] != null) {
            this.getChildControl("timefield").setPlaceholder(p[1]);
        }
    },


    /*
    ---------------------------------------------------------------------------
      WIDGET API

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

     */
    isEmpty: function()
    {
      var value = this.getChildControl("datefield").getValue();
      return value == null || value == "";
    }
  },


  destruct : function() {
    // listen for locale changes
    if (qx.core.Environment.get("qx.dynlocale"))
    {
      if (this.__localeListenerId) {
        qx.locale.Manager.getInstance().removeListenerById(this.__localeListenerId);
      }
    }
  }
});

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/renderer/NoteForm.js  view on Meta::CPAN

                                    })
                            } catch (err) {
                                msg.info(that.tr("Copy failed"), copyFailMsg);
                            }
                        });
                    }
                    that._row += 2;
                    that._connectVisibility(item, label);

                    // store the names for translation
                    if (qx.core.Environment.get("qx.dynlocale")) {
                        that._names.push({
                            name: names[i], label: label, item: items[i]
                        });
                    }
                })();
            } // end context
            let bounds = this.getBounds();
            if (bounds) {
                this._updateForm(bounds.width);
            }



( run in 0.939 second using v1.01-cache-2.11-cpan-ceb78f64989 )