Version 19 of An i15d date chooser

Updated 2004-07-20 04:29:31

Richard Suchenwirth - i15d: internationalized. This is the second attempt at a calendar widget (for the first see A little date chooser). Instead of fiddling packer geometry, it now has all controls on a canvas; displays days in neighboring months (grayed out, not selectable); you can configure the weekday sequence to start with Sunday or Monday; but best of all, allows on-the-fly reconfiguration of the language used for month and weekday names. Language data is provided for English, German, French, Italian, Russian, Swedish and Chinese; feel free to add more. Enjoy!

http://mini.net/files/i15dcal.jpg


Someone added Japanese (ja). MS did Spanish. JCW did Dutch (nl). GP-L added some missing accents in French (fr). Peter Lewerin added Swedish (sv). ECS added Portuguese (pt).


LV and RS talked (was it chat or email) about the use of embedded data vs the use of the tcl msgcat catalog functions. The pro of this is that one could, with proper coding, add new languages without change to the software, and could get some reuse out of the data.

RS pointed out the cons - he didn't want to use the msgcat - he wanted an all in one tcl script rather than a series of files. Perhaps both could be accomidated by someone providing some tcl scripts that take embedded tcl data and writing it out to the msg cat; that way, the app could create/update one's msgcat if new info was available...

VL 7 jun 2003 - Perhaps you are looking for msgcatx? Extracts msgcat-catalogues with some comments on where in the code and also he sort of object the string is contained in. Part of my Mimers brunn project [L1 ], not done much work since last spring but it is definitely usable and I'll be working on a UI to it when I get some spare time.

It's not clear to me why msgcat and "all in one tcl script" are incompatible? A message catalog is just a Tcl script with one or more mcset or mcmset commands. Can't we have:

    mcset en Mon Monday
    mcset it Mon Lunedi
    ...

or

    mcmset en {
        Mon Monday
        Tue Tuesday
        ...
    }
    mcmset it {
        Mon Lunedi
        Tue Martedi
        ...
    }
    ...

at the top of the script? -- CLN

VL 7 jun 2003 - For small scripts this would be pheasable, but it sort of takes the point out of localization, the idea is to make it easy to translate without having to go into the code and do changes.

LV for that matter - perhaps some kind of conditional command - if this catalog entry does not exist, then create it. However, the user would have to have write permission in the catalog area - something that many of us would be unlikely to want to provide.

VL 7 jun 2003 - The default if a catalogue is missing is to use the initial message, or en if it is provided. For a good idea of how to work with localizing your applications do take a look at the Free Translation Project [L2 ]

SH 08 jul 2003 - Fixed bug in which days for 'pt' display instead of english, and 'pt' missing.


When I resize this widget, the numbers and words don't grow - is there a way to code Tk widgets so that one can change the size (so that old people can read the words...)


 package require msgcat
 package require Tk
 namespace eval date {
    variable a
    set now [clock scan now]
    set a(year) [clock format $now -format "%Y"]
    scan [clock format $now -format "%m"] %d a(month) 
    scan [clock format $now -format "%d"] %d a(day)
         [clock format $now -format "%d"] %d a(day)
    proc chooser {w args} {
        variable a
        array set a {
            -font {Helvetica 9} -titlefont {Helvetica 12} -bg white
            -highlight orange -mon 1
        }
        # The -mon switch gives the position of Monday (1 or 0)
        array set a $args
        set a(canvas) [canvas $w -bg $a(-bg) -width 200 -height 180]
        $w bind day <1> {
                set item [%W find withtag current]
                set date::a(day) [%W itemcget $item -text]
                date::display
            }
        cbutton $w 60  10 << {date::adjust  0 -1}
        cbutton $w 80  10 <  {date::adjust -1  0}
        cbutton $w 120 10 >  {date::adjust  1  0}
        cbutton $w 140 10 >> {date::adjust  0  1}
        display
        set w
    }
    proc adjust {dmonth dyear} {
        variable a
        incr a(year)  $dyear
        incr a(month) $dmonth
        if {$a(month)>12} {set a(month) 1; incr a(year)}
        if {$a(month)<1}  {set a(month) 12; incr a(year) -1}
        set maxday [numberofdays $a(month) $a(year)]
        if {$maxday < $a(day)} {set a(day) $maxday}
        display
    }
    proc display {} {
        variable a
        set c $a(canvas)
        foreach tag {title otherday day} {$c delete $tag}
        set x0 20; set x $x0; set y 50
        set dx 25; set dy 20
        set xmax [expr {$x0+$dx*6}]
        set a(date) [clock scan $a(month)/$a(day)/$a(year)]
        set title [format [monthname $a(month)] $a(year)]
        $c create text [expr ($xmax+$dx)/2] 30 -text $title -fill blue \
            -font $a(-titlefont) -tag title
        set weekdays $a(weekdays,$a(language))
        if !$a(-mon) {lcycle weekdays}
        foreach i $weekdays {
            $c create text $x $y -text $i -fill blue \
                -font $a(-font) -tag title
            incr x $dx
        }
        set first $a(month)/1/$a(year)
        set weekday [clock format [clock scan $first] -format %w]
        if !$a(-mon) {set weekday [expr {($weekday+6)%7}]}
        set x [expr {$x0+$weekday*$dx}]
        set x1 $x; set offset 0
        incr y $dy
        while {$weekday} {
            set t [clock scan "$first [incr offset] days ago"]
            scan [clock format $t -format "%d"] %d day
            $c create text [incr x1 -$dx] $y -text $day \
                -fill grey -font $a(-font) -tag otherday
            incr weekday -1
        }
        set dmax [numberofdays $a(month) $a(year)]
        for {set d 1} {$d<=$dmax} {incr d} {
            set id [$c create text $x $y -text $d -tag day -font $a(-font)]
            if {$d==$a(day)} {
                eval $c create rect [$c bbox $id] \
                    -fill $a(-highlight) -outline $a(-highlight) -tag day
            }
            $c raise $id
            if {[incr x $dx]>$xmax} {set x $x0; incr y $dy}
        }
        if {$x != $x0} {
            for {set d 1} {$x<=$xmax} {incr d; incr x $dx} {
                $c create text $x $y -text $d \
                    -fill grey -font $a(-font) -tag otherday
            }
        }
    }
    proc format {month year} {
        variable a
        if ![info exists a(format,$a(language))] {
            set format "%m %y" ;# default
        } else {set format $a(format,$a(language))}
        foreach {from to} [list %m $month %y $year] {
            regsub $from $format $to format
        }
        subst $format
    }
    proc monthname {month {language default}} {
        variable a
        if {$language=="default"} {set language $a(language)}
        if {[info exists a(mn,$language)]} {
            set res [lindex $a(mn,$language) $month]
        } else {set res $month} 
    }
    array set a {
        language en
        mn,de {
        . Januar Februar M��¤rz April Mai Juni Juli August
        September Oktober November Dezember
        }
        weekdays,de {So Mo Di Mi Do Fr Sa}

        mn,en {
        . January February March April May June July August
        September October November December
        }
        weekdays,en {Sun Mon Tue Wed Thu Fri Sat}

        mn,es {
        . Enero Febrero Marzo Abril Mayo Junio Julio Agosto
        Septiembre Octubre Noviembre Diciembre
        }
        weekdays,es {Do Lu Ma Mi Ju Vi Sa}

        mn,fr {
        . Janvier F��©vrier Mars Avril Mai Juin Juillet Ao��»t
        Septembre Octobre Novembre D��©cembre
        }
        weekdays,fr {Di Lu Ma Me Je Ve Sa}

mn,he { ינואר פברואר מרץ אפריל מאי יוני יולי אוגוסט ספטמבר אוקטובר נובמבר } weekdays,he {ראשון שני שלישי רביעי חמישי שישי שבת}

        mn,it {
        . Gennaio Febraio Marte Aprile Maggio Giugno Luglio Agosto
        Settembre Ottobre Novembre Dicembre
        }
        weekdays,it {Do Lu Ma Me Gi Ve Sa}

        format,ja {%y\u5e74 %m\u6708}
        weekdays,ja {\u65e5 \u6708 \u706b \u6c34 \u6728 \u91d1 \u571f}

        mn,nl {
        . januari februari maart april mei juni juli augustus
        september oktober november december
        }
        weekdays,nl {Zo Ma Di Wo Do Vr Za}

        mn,ru {
        . \u42f\u43d\u432\u430\u440\u44c \u424\u435\u432\u440\u430\u43b\u44c
        \u41c\u430\u440\u442 \u410\u43f\u440\u435\u43b\u44c
        \u41c\u430\u439 \u418\u44e\u43d\u439 \u418\u44e\u43b\u439
        \u410\u432\u433\u443\u441\u442
        \u421\u435\u43d\u442\u44f\u431\u440\u44c
        \u41e\u43a\u442\u44f\u431\u440 \u41d\u43e\u44f\u431\u440
        \u414\u435\u43a\u430\u431\u440
        }
        weekdays,ru {
            \u432\u43e\u441 \u43f\u43e\u43d \u432\u442\u43e \u441\u440\u435
            \u447\u435\u442 \u43f\u44f\u442 \u441\u443\u431
        }

        mn,sv {
            . januari februari mars april maj juni juli augusti
            september oktober november december
        }
        weekdays,sv {s��¶n m��¥n tis ons tor fre l��¶r}

        mn,pt {
        . Janeiro Fevereiro Março Abril Maio Junho
        Julho Agosto Setembro Outubro Novembro Dezembro
        }
        weekdays,pt {Dom Seg Ter Qua Qui Sex Sab}

        format,zh {%y\u5e74 %m\u6708}
        mn,zh {
            . \u4e00 \u4e8c \u4e09 \u56db \u4e94 \u516d \u4e03
              \u516b \u4e5d \u5341 \u5341\u4e00 \u5341\u4e8c
        }
        weekdays,zh {\u65e5 \u4e00 \u4e8c \u4e09 \u56db \u4e94 \u516d}
        mn,fi {
          . Tammikuu Helmikuu Maaliskuu Huhtikuu Toukokuu Kes��¤kuu
          Hein��¤kuu Elokuu Syyskuu Lokakuu Marraskuu Joulukuu
        }
        weekdays,fi {Ma Ti Ke To Pe La Su}
        mn,tr {
           . ocak \u015fubat mart nisan may\u0131s haziran temmuz a\u011fustos eyl��¼l ekim kas\u0131m aral\u0131k
        }
        weekdays,tr {pa'tesi sa \u00e7a pe cu cu'tesi pa}
    }
    proc numberofdays {month year} {
        if {$month==12} {set month 0; incr year}
        clock format [clock scan "[incr month]/1/$year  1 day ago"] \
            -format %d
    } 
 } ;# end namespace date

 proc lcycle _list {
    upvar $_list list
    set list [concat [lrange $list 1 end] [list [lindex $list 0]]]
 }
 proc cbutton {w x y text command} {
    set txt [$w create text $x $y -text " $text "]
    set btn [eval $w create rect [$w bbox $txt] \
        -fill grey -outline grey]
    $w raise $txt
    foreach i [list $txt $btn] {$w bind $i <1> $command}
 }

 #------ test and demo code (terminate by closing the main window)
 date::chooser .1
 entry .2 -textvar date::a(date)
 regsub -all weekdays, [array names date::a weekdays,*] "" languages
 foreach i [lsort $languages] {
    radiobutton .b$i -text $i -variable date::a(language) -value $i -pady 0
 }
 trace variable date::a(language) w {date::display ;#}
 checkbutton .mon -variable date::a(-mon) -text "Sunday starts week"
 trace variable date::a(-mon) w {date::display ;#}

 eval pack [winfo children .] -fill x -anchor w


The classic Tcl calendar application is ical. Unfortunately, ical doesn't appear to be supported at this time.


i18n - writing for the world - Arts and crafts of Tcl-Tk programming


Category Package | Category GUI | Category Widget | Category Date and Time