Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit ae785dfc4af21d71b0b66128b0988a7811ad53bb 0 parents
@espern espern authored
Showing with 18,194 additions and 0 deletions.
  1. +2 −0  ABOUT
  2. +4 −0 LICENSE
  3. +1 −0  __init__.py
  4. +4 −0 cache/.gitignore
  5. +461 −0 controllers/appadmin.py
  6. +101 −0 controllers/calendar.py
  7. +172 −0 controllers/default.py
  8. +42 −0 controllers/files.py
  9. +114 −0 controllers/images.py
  10. +42 −0 controllers/news.py
  11. +73 −0 controllers/pages.py
  12. 0  controllers/website_tools.py
  13. +1 −0  cron/crontab
  14. +1 −0  cron/crontab.example
  15. +4 −0 databases/.gitignore
  16. +4 −0 errors/.gitignore
  17. +189 −0 languages/cs.py
  18. +122 −0 languages/default.py
  19. +318 −0 languages/es.py
  20. +195 −0 languages/fr-ca.py
  21. +449 −0 languages/fr.py
  22. +149 −0 languages/hi.py
  23. +162 −0 languages/hu.py
  24. +239 −0 languages/it.py
  25. +376 −0 languages/nl.py
  26. +171 −0 languages/pl.py
  27. +15 −0 languages/plural-en.py
  28. +16 −0 languages/plural-ru.py
  29. +17 −0 languages/plural-uk.py
  30. +170 −0 languages/pt-br.py
  31. +184 −0 languages/pt.py
  32. +373 −0 languages/ro.py
  33. +195 −0 languages/ru.py
  34. +171 −0 languages/sk.py
  35. +221 −0 languages/uk.py
  36. +231 −0 languages/zh.py
  37. +98 −0 models/db.py
  38. +113 −0 models/db__website.py
  39. +32 −0 models/db_calendar.py
  40. +47 −0 models/db_menu.py
  41. +52 −0 models/menu.py
  42. +156 −0 models/x_fixtures.py
  43. +1 −0  modules/__init__.py
  44. +24 −0 modules/models_tools.py
  45. +4 −0 private/.gitignore
  46. +39 −0 routes.example.py
  47. +4 −0 sessions/.gitignore
  48. +9 −0 static/css/bootstrap-responsive.min.css
  49. +9 −0 static/css/bootstrap.min.css
  50. +7 −0 static/css/calendar.css
  51. +618 −0 static/css/fullcalendar.css
  52. +310 −0 static/css/web2py.css
  53. +231 −0 static/css/web2py_bootstrap.css
  54. +122 −0 static/css/web2py_bootstrap_nojs.css
  55. +172 −0 static/css/x_application.css
  56. BIN  static/images/add-icon.png
  57. BIN  static/images/banner/banner.jpg
  58. BIN  static/images/delete-icon.png
  59. BIN  static/images/edit-icon.png
  60. BIN  static/images/facebook.png
  61. BIN  static/images/favicon.ico
  62. BIN  static/images/favicon.png
  63. BIN  static/images/feed-icon.png
  64. BIN  static/images/glyphicons-halflings-white.png
  65. BIN  static/images/glyphicons-halflings.png
  66. BIN  static/images/google-buzz.png
  67. BIN  static/images/gplus-32.png
  68. +4 −0 static/images/pages_content/.gitignore
  69. +4 −0 static/images/photo_gallery/.gitignore
  70. BIN  static/images/twitter.png
  71. +6 −0 static/js/bootstrap.min.js
  72. +42 −0 static/js/calendar.js
  73. +13 −0 static/js/dd_belatedpng.js
  74. +5,220 −0 static/js/fullcalendar.js
  75. +114 −0 static/js/fullcalendar.min.js
  76. +2 −0  static/js/jquery.js
  77. +4 −0 static/js/modernizr.custom.js
  78. +44 −0 static/js/share.js
  79. +519 −0 static/js/ui.core.js
  80. +766 −0 static/js/ui.draggable.js
  81. +800 −0 static/js/ui.resizable.js
  82. +202 −0 static/js/web2py.js
  83. +28 −0 static/js/web2py_bootstrap.js
  84. +112 −0 static/nicEdit/nicEdit.js
  85. +1,464 −0 static/nicEdit/nicEditComplete.js
  86. BIN  static/nicEdit/nicEditorIcons.gif
  87. +192 −0 static/nicEdit/nicUpload.php
  88. BIN  static/polices/blackjar-webfont.eot
  89. +214 −0 static/polices/blackjar-webfont.svg
  90. BIN  static/polices/blackjar-webfont.ttf
  91. BIN  static/polices/blackjar-webfont.woff
  92. BIN  static/polices/dafont/BLACKJAR.TTF
  93. BIN  static/polices/dafont/DAYROM_X.ttf
  94. BIN  static/polices/dafont/DAYROM__.ttf
  95. BIN  static/polices/dayrom__-webfont.eot
  96. +249 −0 static/polices/dayrom__-webfont.svg
  97. BIN  static/polices/dayrom__-webfont.ttf
  98. BIN  static/polices/dayrom__-webfont.woff
  99. +5 −0 static/polices/generator_config.txt
  100. +28 −0 static/polices/stylesheet.css
  101. +4 −0 static/uploaded_files/.gitignore
  102. 0  tests/__init__.py
  103. +5 −0 tests/sql.log
  104. +45 −0 tests/test.py
  105. +4 −0 uploads/.gitignore
  106. +1 −0  views/__init__.py
  107. +224 −0 views/appadmin.html
  108. +79 −0 views/calendar/calendar.load
  109. +11 −0 views/calendar/calendar_booking.html
  110. +2 −0  views/calendar/edit_booking_requests.html
  111. +23 −0 views/default/address.load
  112. +10 −0 views/default/contact_form.html
  113. +4 −0 views/default/newsletter.load
  114. +23 −0 views/default/user.html
  115. +4 −0 views/files/delete_file.html
  116. +8 −0 views/files/edit_file.html
  117. +31 −0 views/files/files.load
  118. +13 −0 views/files/files_list.html
  119. +16 −0 views/generic.html
  120. +17 −0 views/generic.ics
  121. +1 −0  views/generic.json
  122. +16 −0 views/generic.jsonp
  123. +30 −0 views/generic.load
  124. +69 −0 views/generic.map
  125. BIN  views/generic.pdf
  126. +10 −0 views/generic.rss
  127. +1 −0  views/generic.xml
  128. +4 −0 views/images/delete_image.html
  129. +10 −0 views/images/edit_image.html
  130. +107 −0 views/images/images.html
  131. +36 −0 views/images/photo_gallery.load
  132. +172 −0 views/layout.html
  133. +4 −0 views/news/delete_news.html
  134. +20 −0 views/news/edit_news.html
  135. +33 −0 views/news/news.load
  136. +2 −0  views/news/news_list.html
  137. +4 −0 views/pages/delete_page.html
  138. +23 −0 views/pages/edit_page.html
  139. +45 −0 views/pages/show_page.html
  140. +14 −0 views/web2py_ajax.html
2  ABOUT
@@ -0,0 +1,2 @@
+Write something about this app.
+Developed with web2py.
4 LICENSE
@@ -0,0 +1,4 @@
+The web2py welcome app is licensed under public domain
+(except for the css and js files that it includes, which have their own third party licenses).
+
+You can modify this license when you add your own code.
1  __init__.py
@@ -0,0 +1 @@
+
4 cache/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
461 controllers/appadmin.py
@@ -0,0 +1,461 @@
+# -*- coding: utf-8 -*-
+
+# ##########################################################
+# ## make sure administrator is on localhost
+# ###########################################################
+
+import os
+import socket
+import datetime
+import copy
+import gluon.contenttype
+import gluon.fileutils
+
+response.subtitle = 'Database Administration (appadmin)'
+
+# ## critical --- make a copy of the environment
+
+global_env = copy.copy(globals())
+global_env['datetime'] = datetime
+
+http_host = request.env.http_host.split(':')[0]
+remote_addr = request.env.remote_addr
+try:
+ hosts = (http_host, socket.gethostname(),
+ socket.gethostbyname(http_host),
+ '::1', '127.0.0.1', '::ffff:127.0.0.1')
+except:
+ hosts = (http_host, )
+
+if request.env.http_x_forwarded_for or request.is_https:
+ session.secure()
+elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1"):
+ raise HTTP(200, T('appadmin is disabled because insecure channel'))
+
+if (request.application == 'admin' and not session.authorized) or \
+ (request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
+ redirect(URL('admin', 'default', 'index',
+ vars=dict(send=URL(args=request.args, vars=request.vars))))
+
+ignore_rw = True
+response.view = 'appadmin.html'
+response.menu = [[T('design'), False, URL('admin', 'default', 'design',
+ args=[request.application])], [T('db'), False,
+ URL('index')], [T('state'), False,
+ URL('state')], [T('cache'), False,
+ URL('ccache')]]
+
+# ##########################################################
+# ## auxiliary functions
+# ###########################################################
+
+
+def get_databases(request):
+ dbs = {}
+ for (key, value) in global_env.items():
+ cond = False
+ try:
+ cond = isinstance(value, GQLDB)
+ except:
+ cond = isinstance(value, SQLDB)
+ if cond:
+ dbs[key] = value
+ return dbs
+
+
+databases = get_databases(None)
+
+
+def eval_in_global_env(text):
+ exec ('_ret=%s' % text, {}, global_env)
+ return global_env['_ret']
+
+
+def get_database(request):
+ if request.args and request.args[0] in databases:
+ return eval_in_global_env(request.args[0])
+ else:
+ session.flash = T('invalid request')
+ redirect(URL('index'))
+
+
+def get_table(request):
+ db = get_database(request)
+ if len(request.args) > 1 and request.args[1] in db.tables:
+ return (db, request.args[1])
+ else:
+ session.flash = T('invalid request')
+ redirect(URL('index'))
+
+
+def get_query(request):
+ try:
+ return eval_in_global_env(request.vars.query)
+ except Exception:
+ return None
+
+
+def query_by_table_type(tablename, db, request=request):
+ keyed = hasattr(db[tablename], '_primarykey')
+ if keyed:
+ firstkey = db[tablename][db[tablename]._primarykey[0]]
+ cond = '>0'
+ if firstkey.type in ['string', 'text']:
+ cond = '!=""'
+ qry = '%s.%s.%s%s' % (
+ request.args[0], request.args[1], firstkey.name, cond)
+ else:
+ qry = '%s.%s.id>0' % tuple(request.args[:2])
+ return qry
+
+
+# ##########################################################
+# ## list all databases and tables
+# ###########################################################
+def index():
+ return dict(databases=databases)
+
+
+# ##########################################################
+# ## insert a new record
+# ###########################################################
+
+
+def insert():
+ (db, table) = get_table(request)
+ form = SQLFORM(db[table], ignore_rw=ignore_rw)
+ if form.accepts(request.vars, session):
+ response.flash = T('new record inserted')
+ return dict(form=form, table=db[table])
+
+
+# ##########################################################
+# ## list all records in table and insert new record
+# ###########################################################
+
+
+def download():
+ import os
+ db = get_database(request)
+ return response.download(request, db)
+
+
+def csv():
+ import gluon.contenttype
+ response.headers['Content-Type'] = \
+ gluon.contenttype.contenttype('.csv')
+ db = get_database(request)
+ query = get_query(request)
+ if not query:
+ return None
+ response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\
+ % tuple(request.vars.query.split('.')[:2])
+ return str(db(query, ignore_common_filters=True).select())
+
+
+def import_csv(table, file):
+ table.import_from_csv_file(file)
+
+
+def select():
+ import re
+ db = get_database(request)
+ dbname = request.args[0]
+ regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
+ if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
+ regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
+ if request.vars.query:
+ match = regex.match(request.vars.query)
+ if match:
+ request.vars.query = '%s.%s.%s==%s' % (request.args[0],
+ match.group('table'), match.group('field'),
+ match.group('value'))
+ else:
+ request.vars.query = session.last_query
+ query = get_query(request)
+ if request.vars.start:
+ start = int(request.vars.start)
+ else:
+ start = 0
+ nrows = 0
+ stop = start + 100
+ table = None
+ rows = []
+ orderby = request.vars.orderby
+ if orderby:
+ orderby = dbname + '.' + orderby
+ if orderby == session.last_orderby:
+ if orderby[0] == '~':
+ orderby = orderby[1:]
+ else:
+ orderby = '~' + orderby
+ session.last_orderby = orderby
+ session.last_query = request.vars.query
+ form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
+ _name='query', _value=request.vars.query or '',
+ requires=IS_NOT_EMPTY(
+ error_message=T("Cannot be empty")))), TR(T('Update:'),
+ INPUT(_name='update_check', _type='checkbox',
+ value=False), INPUT(_style='width:400px',
+ _name='update_fields', _value=request.vars.update_fields
+ or '')), TR(T('Delete:'), INPUT(_name='delete_check',
+ _class='delete', _type='checkbox', value=False), ''),
+ TR('', '', INPUT(_type='submit', _value=T('submit')))),
+ _action=URL(r=request, args=request.args))
+
+ tb = None
+ if form.accepts(request.vars, formname=None):
+ regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
+ match = regex.match(form.vars.query.strip())
+ if match:
+ table = match.group('table')
+ try:
+ nrows = db(query).count()
+ if form.vars.update_check and form.vars.update_fields:
+ db(query).update(**eval_in_global_env('dict(%s)'
+ % form.vars.update_fields))
+ response.flash = T('%s %%{row} updated', nrows)
+ elif form.vars.delete_check:
+ db(query).delete()
+ response.flash = T('%s %%{row} deleted', nrows)
+ nrows = db(query).count()
+ if orderby:
+ rows = db(query, ignore_common_filters=True).select(limitby=(
+ start, stop), orderby=eval_in_global_env(orderby))
+ else:
+ rows = db(query, ignore_common_filters=True).select(
+ limitby=(start, stop))
+ except Exception, e:
+ import traceback
+ tb = traceback.format_exc()
+ (rows, nrows) = ([], 0)
+ response.flash = DIV(T('Invalid Query'), PRE(str(e)))
+ # begin handle upload csv
+ csv_table = table or request.vars.table
+ if csv_table:
+ formcsv = FORM(str(T('or import from csv file')) + " ",
+ INPUT(_type='file', _name='csvfile'),
+ INPUT(_type='hidden', _value=csv_table, _name='table'),
+ INPUT(_type='submit', _value=T('import')))
+ else:
+ formcsv = None
+ if formcsv and formcsv.process().accepted:
+ try:
+ import_csv(db[request.vars.table],
+ request.vars.csvfile.file)
+ response.flash = T('data uploaded')
+ except Exception, e:
+ response.flash = DIV(T('unable to parse csv file'), PRE(str(e)))
+ # end handle upload csv
+
+ return dict(
+ form=form,
+ table=table,
+ start=start,
+ stop=stop,
+ nrows=nrows,
+ rows=rows,
+ query=request.vars.query,
+ formcsv=formcsv,
+ tb=tb,
+ )
+
+
+# ##########################################################
+# ## edit delete one record
+# ###########################################################
+
+
+def update():
+ (db, table) = get_table(request)
+ keyed = hasattr(db[table], '_primarykey')
+ record = None
+ if keyed:
+ key = [f for f in request.vars if f in db[table]._primarykey]
+ if key:
+ record = db(db[table][key[0]] == request.vars[key[
+ 0]], ignore_common_filters=True).select().first()
+ else:
+ record = db(db[table].id == request.args(
+ 2), ignore_common_filters=True).select().first()
+
+ if not record:
+ qry = query_by_table_type(table, db)
+ session.flash = T('record does not exist')
+ redirect(URL('select', args=request.args[:1],
+ vars=dict(query=qry)))
+
+ if keyed:
+ for k in db[table]._primarykey:
+ db[table][k].writable = False
+
+ form = SQLFORM(
+ db[table], record, deletable=True, delete_label=T('Check to delete'),
+ ignore_rw=ignore_rw and not keyed,
+ linkto=URL('select',
+ args=request.args[:1]), upload=URL(r=request,
+ f='download', args=request.args[:1]))
+
+ if form.accepts(request.vars, session):
+ session.flash = T('done!')
+ qry = query_by_table_type(table, db)
+ redirect(URL('select', args=request.args[:1],
+ vars=dict(query=qry)))
+ return dict(form=form, table=db[table])
+
+
+# ##########################################################
+# ## get global variables
+# ###########################################################
+
+
+def state():
+ return dict()
+
+
+def ccache():
+ form = FORM(
+ P(TAG.BUTTON(
+ T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
+ P(TAG.BUTTON(
+ T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
+ P(TAG.BUTTON(
+ T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
+ )
+
+ if form.accepts(request.vars, session):
+ clear_ram = False
+ clear_disk = False
+ session.flash = ""
+ if request.vars.yes:
+ clear_ram = clear_disk = True
+ if request.vars.ram:
+ clear_ram = True
+ if request.vars.disk:
+ clear_disk = True
+
+ if clear_ram:
+ cache.ram.clear()
+ session.flash += T("Ram Cleared")
+ if clear_disk:
+ cache.disk.clear()
+ session.flash += T("Disk Cleared")
+
+ redirect(URL(r=request))
+
+ try:
+ from guppy import hpy
+ hp = hpy()
+ except ImportError:
+ hp = False
+
+ import shelve
+ import os
+ import copy
+ import time
+ import math
+ from gluon import portalocker
+
+ ram = {
+ 'entries': 0,
+ 'bytes': 0,
+ 'objects': 0,
+ 'hits': 0,
+ 'misses': 0,
+ 'ratio': 0,
+ 'oldest': time.time(),
+ 'keys': []
+ }
+ disk = copy.copy(ram)
+ total = copy.copy(ram)
+ disk['keys'] = []
+ total['keys'] = []
+
+ def GetInHMS(seconds):
+ hours = math.floor(seconds / 3600)
+ seconds -= hours * 3600
+ minutes = math.floor(seconds / 60)
+ seconds -= minutes * 60
+ seconds = math.floor(seconds)
+
+ return (hours, minutes, seconds)
+
+ for key, value in cache.ram.storage.items():
+ if isinstance(value, dict):
+ ram['hits'] = value['hit_total'] - value['misses']
+ ram['misses'] = value['misses']
+ try:
+ ram['ratio'] = ram['hits'] * 100 / value['hit_total']
+ except (KeyError, ZeroDivisionError):
+ ram['ratio'] = 0
+ else:
+ if hp:
+ ram['bytes'] += hp.iso(value[1]).size
+ ram['objects'] += hp.iso(value[1]).count
+ ram['entries'] += 1
+ if value[0] < ram['oldest']:
+ ram['oldest'] = value[0]
+ ram['keys'].append((key, GetInHMS(time.time() - value[0])))
+
+ locker = open(os.path.join(request.folder,
+ 'cache/cache.lock'), 'a')
+ portalocker.lock(locker, portalocker.LOCK_EX)
+ disk_storage = shelve.open(
+ os.path.join(request.folder, 'cache/cache.shelve'))
+ try:
+ for key, value in disk_storage.items():
+ if isinstance(value, dict):
+ disk['hits'] = value['hit_total'] - value['misses']
+ disk['misses'] = value['misses']
+ try:
+ disk['ratio'] = disk['hits'] * 100 / value['hit_total']
+ except (KeyError, ZeroDivisionError):
+ disk['ratio'] = 0
+ else:
+ if hp:
+ disk['bytes'] += hp.iso(value[1]).size
+ disk['objects'] += hp.iso(value[1]).count
+ disk['entries'] += 1
+ if value[0] < disk['oldest']:
+ disk['oldest'] = value[0]
+ disk['keys'].append((key, GetInHMS(time.time() - value[0])))
+
+ finally:
+ portalocker.unlock(locker)
+ locker.close()
+ disk_storage.close()
+
+ total['entries'] = ram['entries'] + disk['entries']
+ total['bytes'] = ram['bytes'] + disk['bytes']
+ total['objects'] = ram['objects'] + disk['objects']
+ total['hits'] = ram['hits'] + disk['hits']
+ total['misses'] = ram['misses'] + disk['misses']
+ total['keys'] = ram['keys'] + disk['keys']
+ try:
+ total['ratio'] = total['hits'] * 100 / (total['hits'] +
+ total['misses'])
+ except (KeyError, ZeroDivisionError):
+ total['ratio'] = 0
+
+ if disk['oldest'] < ram['oldest']:
+ total['oldest'] = disk['oldest']
+ else:
+ total['oldest'] = ram['oldest']
+
+ ram['oldest'] = GetInHMS(time.time() - ram['oldest'])
+ disk['oldest'] = GetInHMS(time.time() - disk['oldest'])
+ total['oldest'] = GetInHMS(time.time() - total['oldest'])
+
+ def key_table(keys):
+ return TABLE(
+ TR(TD(B(T('Key'))), TD(B(T('Time in Cache (h:m:s)')))),
+ *[TR(TD(k[0]), TD('%02d:%02d:%02d' % k[1])) for k in keys],
+ **dict(_class='cache-keys',
+ _style="border-collapse: separate; border-spacing: .5em;"))
+
+ ram['keys'] = key_table(ram['keys'])
+ disk['keys'] = key_table(disk['keys'])
+ total['keys'] = key_table(total['keys'])
+
+ return dict(form=form, total=total,
+ ram=ram, disk=disk, object_stats=hp != False)
101 controllers/calendar.py
@@ -0,0 +1,101 @@
+#from gluon.debug import dbg
+
+def calendar():
+ """
+ Allows to access the "calendar" component
+ """
+ month_list = [T('January'),T('February'),T('March'),T('April'),T('May'),T('June'),T('July'),T('August'),T('September'),T('October'),T('November'),T('December')]
+ shortmonth_list = [T('Jan'),T('Feb'),T('Mar'),T('Apr'),T('May'),T('Jun'),T('Jul'),T('Aug'),T('Sep'),T('Oct'),T('Nov'),T('Dec')]
+ day_list = [T('Sunday'),T('Monday'),T('Tuesday'),T('Wednesday'),T('Thursday'),T('Friday'),T('Saturday')]
+ shortday_list = [T('Sun'),T('Mon'),T('Tue'),T('Wed'),T('Thu'),T('Fri'),T('Sat')]
+
+ page = db.page(request.vars.container_id)
+ rows = db(db.calendar_event.page==page)(db.calendar_event.is_confirmed==True).select()
+
+ form = SQLFORM.factory(db.calendar_contact, db.calendar_event)
+ if form.process().accepted:
+ _id = db.calendar_contact.insert(**db.calendar_contact._filter_fields(form.vars))
+ form.vars.contact=_id
+ form.vars.page=request.args(0)
+ _id = db.calendar_event.insert(**db.calendar_event._filter_fields(form.vars))
+
+
+ response.flash = T('Thanks for filling the form')
+ elif form.errors:
+ response.flash = T('form has errors')
+
+ #dbg.set_trace()
+ return dict(rows=rows,
+ form=form,
+ page=page,
+ month_list=month_list,
+ shortmonth_list=shortmonth_list,
+ day_list=day_list,
+ shortday_list=shortday_list)
+
+def calendar_booking():
+ """
+ Add a booking request to a calendar event
+ """
+ page = db.page(request.args(0))
+ if not page:
+ redirect(URL('index'))
+ form = SQLFORM.factory(db.calendar_contact, db.calendar_event)
+ page_low_title = page.title.lower()
+ if form.process().accepted:
+ _id = db.calendar_contact.insert(**db.calendar_contact._filter_fields(form.vars))
+ form.vars.contact=_id
+ form.vars.page=page.id
+ _id = db.calendar_event.insert(**db.calendar_event._filter_fields(form.vars))
+
+ duration = db.calendar_duration(form.vars.duration)
+
+ #send an email
+ message=T("""
+ The following person would like to book %s :
+
+ Name : %s
+ Email : %s
+ Phone number : %s
+ Address : %s
+ From : %s
+ During : %s
+ """) % (page_low_title, form.vars.name, form.vars.email, form.vars.phone_number, form.vars.address,
+ form.vars.start_date.strftime("%d/%m/%Y"), duration.name if duration else '')
+ if mail.send(to=WEBSITE_PARAMETERS.booking_form_email,
+ cc=[WEBSITE_PARAMETERS.booking_form_cc],
+ bcc=[WEBSITE_PARAMETERS.booking_form_bcc],
+ subject=T('Booking request for %s on %s website') % (page_low_title,WEBSITE_PARAMETERS.website_name),
+ reply_to = form.vars.email,
+ message = message):
+ session.flash = T('Your booking request has been recorded. Somebody will contact you as soon as possible. Thank you')
+ redirect(URL('pages','show_page',args=page.url))
+ else:
+ form.errors.your_email = T('Unable to send the email')
+ elif form.errors:
+ response.flash = T('form has errors')
+ return dict(form=form,left_sidebar_enabled=True,right_sidebar_enabled=True)
+
+@auth.requires_membership('booking_manager')
+def edit_booking_requests():
+ db.calendar_event.is_confirmed.readable = db.calendar_event.is_confirmed.writable = True
+ db.calendar_event.page.readable = db.calendar_event.page.writable = True
+ db.calendar_event.contact.readable = db.calendar_event.contact.writable = True
+
+ linked_tables=['page, contact']
+ fields=[db.calendar_event.page,db.calendar_event.contact, db.calendar_event.start_date, db.calendar_event.duration, db.calendar_event.is_confirmed]
+ orderby = db.calendar_event.is_confirmed | ~db.calendar_event.start_date
+ exportclasses=dict(
+ csv_with_hidden_cols=False,
+ xml=False,
+ html=False,
+ csv=False,
+ json=False,
+ tsv_with_hidden_cols=False,
+ tsv=False)
+ grid = SQLFORM.smartgrid(db.calendar_event,
+ linked_tables=linked_tables,
+ exportclasses=exportclasses,
+ orderby=orderby,
+ fields=fields)
+ return dict(grid=grid)
172 controllers/default.py
@@ -0,0 +1,172 @@
+# -*- coding: utf-8 -*-
+
+# from gluon.debug import dbg
+
+########## TODO #################
+#
+# Voir dans le web2py book les URL Rewrite Pattern-based system pour rediriger pusieurs ndd sur des appli différentes
+#
+# Regarder le principe des "Callable" python pour faire un objet "Toolbar", et un callable "Manager_toolbas" qu'on init en passant ou pas un id
+#
+#################################
+
+def index():
+ """
+
+ """
+ page = db(db.page.is_index==True).select().first()
+ if not page:
+ raise HTTP(404, T('sorry, the page you requested does not exist'))
+ redirect(URL('pages','show_page',args=page.url))
+
+
+def user():
+ """
+ exposes:
+ http://..../[app]/default/user/login
+ http://..../[app]/default/user/logout
+ http://..../[app]/default/user/register
+ http://..../[app]/default/user/profile
+ http://..../[app]/default/user/retrieve_password
+ http://..../[app]/default/user/change_password
+ use @auth.requires_login()
+ @auth.requires_membership('group name')
+ @auth.requires_permission('read','table name',record_id)
+ to decorate functions that need access control
+ """
+ return dict(form=auth())
+
+
+def download():
+ """
+ allows downloading of uploaded files
+ http://..../[app]/default/download/[filename]
+ """
+ return response.download(request, db)
+
+def address():
+ """
+ Allows to access the "address" component
+ """
+ return dict()
+
+def newsletter():
+ """
+ Allows to access the "newsletter" component
+ """
+ form = SQLFORM(db.registered_user, _class='blueText')
+ if form.process().accepted:
+ response.flash = T('form accepted')
+ elif form.errors:
+ response.flash = T('form has errors')
+ return dict(form=form)
+
+
+def call():
+ """
+ exposes services. for example:
+ http://..../[app]/default/call/jsonrpc
+ decorate with @services.jsonrpc the functions to expose
+ supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
+ """
+ return service()
+
+
+@auth.requires_signature()
+def data():
+ """
+ http://..../[app]/default/data/tables
+ http://..../[app]/default/data/create/[table]
+ http://..../[app]/default/data/read/[table]/[id]
+ http://..../[app]/default/data/update/[table]/[id]
+ http://..../[app]/default/data/delete/[table]/[id]
+ http://..../[app]/default/data/select/[table]
+ http://..../[app]/default/data/search/[table]
+ but URLs must be signed, i.e. linked with
+ A('table',_href=URL('data/tables',user_signature=True))
+ or with the signed load operator
+ LOAD('default','data.load',args='tables',ajax=True,user_signature=True)
+ """
+ return dict(form=crud())
+
+def contact_form():
+ """
+ Contact form
+ """
+ from gluon.tools import Recaptcha
+
+ public_key = '6LfBX90SAAAAAKZn2zPK5i72PZsnm9Ouj6BC67k7'
+ private_key = '6LfBX90SAAAAADRYFTj5xMyZnZoWycdkCBlF_Djb '
+
+ form=SQLFORM.factory(
+ Field('your_name',requires=IS_NOT_EMPTY(), label=T('Your name')),
+ Field('your_email',requires=IS_EMAIL(), label=T('Your email')),
+ Field('subject',requires=IS_NOT_EMPTY(), label=T('Subject')),
+ Field('message', 'text',requires=IS_NOT_EMPTY(), label=T('Message'))
+ )
+ #form.element('table').insert(-1,(T('Confirm that you are not a machine'),Recaptcha(request, public_key, private_key),''))
+ if form.process().accepted:
+ message=T("""
+ Name : %s
+ Email : %s
+ Subject : %s
+ Message : %s
+ """) % (form.vars.your_name, form.vars.your_email, form.vars.subject, form.vars.message)
+ if mail.send(
+ to=WEBSITE_PARAMETERS.contact_form_email,
+ cc=WEBSITE_PARAMETERS.contact_form_cc,
+ bcc=WEBSITE_PARAMETERS.contact_form_bcc,
+ subject=T('Question from %s on %s website') % (form.vars.your_name,WEBSITE_PARAMETERS.website_name),
+ reply_to = form.vars.your_email,
+ message = message):
+ response.flash = T('Your message has been sent. Thank you')
+ response.js = "jQuery('#%s').hide()" % request.cid
+ else:
+ form.errors.your_email = T('Unable to send the email')
+ return dict(form=form,
+ left_sidebar_enabled=True,
+ right_sidebar_enabled=True)
+
+# def sitemap():
+# # Import Regex
+# from gluon.myregex import regex_expose
+
+# # Finding You Controllers
+# ctldir = os.path.join(request.folder,"controllers")
+# ctls=os.listdir(ctldir)
+# # Excluding The appadmin.py and the Manage.py
+# if 'appadmin.py' in ctls: ctls.remove('appadmin.py')
+# if 'manage.py' in ctls: ctls.remove('manage.py')
+
+# # Adding Schemas for the site map
+# xmlns='xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n'
+# xmlnsImg='xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"\n'
+# xmlnsVid='xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"\n'
+# sitemap_xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
+# sitemap_xml +='<urlset %s %s %s>\n'%(xmlns,xmlnsImg,xmlnsVid)
+
+# # Add The Pages That You Dont want in the XML Sitemap
+# ExcludedPages = ['Function_Name']
+
+# # Define Your Domain
+# Domain = WEBSITE_PARAMETERS.website_url
+
+# for ctl in ctls:
+# if ctl.endswith(".bak") == False:
+# filename = os.path.join(ctldir,ctl)
+# data = open(filename, 'r').read()
+# functions = regex_expose.findall(data)
+# ctl = ctl[:-3].replace("_"," ")
+
+# # Adding Statics URLs From Your Controllers
+# for f in functions:
+# # Ignore the Pages from the list above ( ExcludedPages )
+# if f not in ExcludedPages:
+# sitemap_xml += '<url>\n<loc>%s/%s/%s</loc>\n</url>\n' %(Domain,ctl,f.replace("_"," "))
+
+# # Dynamic URLs From Tables For ex ... >> www.domain.com/post/1
+# pages = db().select(db.page.ALL)
+# for page in pages:
+# sitemap_xml += '<url>\n<loc>%s/default/show_page/%s</loc>\n</url>\n' %(Domain,page.url)
+# sitemap_xml +='</urlset>'
+# return sitemap_xml
42 controllers/files.py
@@ -0,0 +1,42 @@
+def files_list():
+ """
+ Allows to access the "files" component
+ """
+ def sizeof_file(num):
+ for x in [T('bytes'),T('KB'),T('MB'),T('GB')]:
+ if num < 1024.0 and num > -1024.0:
+ return "%3.1f%s" % (num, x)
+ num /= 1024.0
+ return "%3.1f%s" % (num, T('TB'))
+
+ manager_toolbar = ManagerToolbar('file')
+ files = db(db.file).select()
+ return dict(files=files,
+ sizeof_file=sizeof_file,
+ left_sidebar_enabled=True,
+ right_sidebar_enabled=True,
+ manager_toolbar=manager_toolbar)
+
+@auth.requires_membership('manager')
+def edit_file():
+ a_file = db.file(request.args(0))
+ crud.settings.update_deletable=False
+ if len(request.args) and a_file:
+ crud.settings.update_deletable = False
+ form = crud.update(db.file,a_file,next='files_list')
+ else:
+ form = crud.create(db.file)
+ return dict(a_file=a_file, form=form)
+
+
+@auth.requires_membership('manager')
+def delete_file():
+ a_file = db.file(request.args(0))
+ if len(request.args) and a_file:
+ form = FORM.confirm(T('Yes, I really want to delete this file'),{T('Back'):URL('files_list')})
+ if form.accepted:
+ #remove the file
+ db(db.file.id==a_file.id).delete()
+ session.flash = T('File deleted')
+ redirect(URL('files_list'))
+ return dict(a_file=a_file, form=form)
114 controllers/images.py
@@ -0,0 +1,114 @@
+#from gluon.debug import dbg
+
+def photo_gallery():
+ """
+ Allows to access the "photo_gallery" component
+ """
+ manager_toolbar = ManagerToolbar('image')
+ MAX_IMAGES = 2
+ images = db(db.image.show_in_gallery==1).select(limitby=(0,MAX_IMAGES), orderby='<random>')
+ return dict(enum_images=enumerate(images),
+ MAX_IMAGES=MAX_IMAGES,
+ manager_toolbar=manager_toolbar)
+
+
+@auth.requires_membership('manager')
+def delete_image():
+ image = db.image(request.args(0))
+ if image:
+ form = FORM.confirm(T('Yes, I really want to delete this image'),{T('Back'):URL('images')})
+ if form.accepted:
+ #remove image and thumb
+ pathname = os.path.join(request.folder,'static','images', 'photo_gallery', str(form.vars.file))
+ if os.path.exists(pathname):
+ shutil.rmtree(pathname)
+ pathname = os.path.join(request.folder,'static','images', 'photo_gallery', str(form.vars.thumb))
+ if os.path.exists(pathname):
+ shutil.rmtree(pathname)
+ #remove the image
+ db(db.image.id==image.id).delete()
+ session.flash = T('Image deleted')
+ redirect(URL('images'))
+ return dict(image=image, form=form)
+
+@auth.requires_membership('manager')
+def edit_image():
+ """
+ Allows to add images in the library
+ """
+ thumb=""
+ if len(request.args):
+ image = db(db.image.id==request.args(0)).select().first()
+ if len(request.args) and image:
+ form = SQLFORM(db.image, image, deletable=True, showid=False)
+ thumb = image.thumb
+ else:
+ form = SQLFORM(db.image)
+ if form.accepts(request.vars, session):
+ response.flash = T('form accepted')
+ #resize the original image to a better size and create a thumbnail
+ __makeThumbnail(db.image,form.vars.id,(800,800),(260,260))
+ redirect(URL('images'))
+ elif form.errors:
+ response.flash = T('form has errors')
+ return dict(form=form,list=list,thumb=thumb)
+
+def images():
+ manager_toolbar = ManagerToolbar('image')
+ images_list = [image for image in db().select(db.image.ALL)]
+ MAX_IMAGES = len(images_list)
+ return dict(images_list=images_list,
+ MAX_IMAGES=MAX_IMAGES,
+ manager_toolbar=manager_toolbar)
+
+def __makeThumbnail(dbtable,ImageID,image_size=(600,600), thumbnail_size=(260,260)):
+ #dbg.set_trace() # stop here!
+ try:
+ thisImage=db(dbtable.id==ImageID).select()[0]
+ import uuid
+ from PIL import Image
+ except: return
+
+ full_path = os.path.join(request.folder,'static','images','photo_gallery',thisImage.file)
+ im = Image.open(full_path)
+ im.thumbnail(image_size,Image.ANTIALIAS)
+ im.save(full_path)
+ thumbName='thumb.%s' % (thisImage.file)
+ full_path = os.path.join(request.folder,'static','images','photo_gallery', 'thumbs',thumbName)
+ im.thumbnail(thumbnail_size,Image.ANTIALIAS)
+ im.save(full_path)
+ thisImage.update_record(thumb=thumbName)
+ return
+
+def nicedit_image_upload():
+ """
+ Controller to upload images with nicedit
+ """
+ from gluon.contrib.simplejson import dumps
+
+ page_id = request.args(0)
+ pathname = os.path.join(request.folder,'static','images', 'pages_content', page_id)
+ if not os.path.exists(pathname):
+ os.mkdir(pathname)
+
+ pathfilename = os.path.join(pathname, request.vars.image.filename)
+ dest_file = open(pathfilename, 'wb')
+
+ try:
+ dest_file.write(request.vars.image.file.read())
+ finally:
+ dest_file.close()
+
+ #Make a thumbnail (max 600*600px) of the uploaded Image
+ try:
+ from PIL import Image
+ im = Image.open(pathfilename)
+ im.thumbnail((600,600),Image.ANTIALIAS)
+ im.save(pathfilename)
+ except:
+ pass
+ links_dict = {"original":URL('static', 'images/pages_content/'+page_id+'/'+request.vars.image.filename)}
+ set_dict = {"links" : links_dict}
+ upload_dict = {"upload" : set_dict}
+
+ return dumps(upload_dict)
42 controllers/news.py
@@ -0,0 +1,42 @@
+def news():
+ """
+ Allows to access the "news" component
+ """
+ manager_toolbar = ManagerToolbar('news')
+ newsS = db(db.news).select(limitby=(0,5),orderby=~db.news.date|~db.news.published_on)
+ return dict(newsS=newsS,
+ manager_toolbar=manager_toolbar)
+
+@auth.requires_membership('manager')
+def edit_news():
+ news = db.news(request.args(0))
+ crud.settings.update_deletable=False
+ if len(request.args) and news:
+ form = crud.update(db.news,news,next=URL('default','index'))
+ else:
+ form = crud.create(db.news,URL('default','index'))
+ return dict(news=news, form=form)
+
+@auth.requires_membership('manager')
+def delete_news():
+ news = db.news(request.args(0))
+ if len(request.args) and news:
+ form = FORM.confirm(T('Yes, I really want to delete this news'),{T('Back'):URL('index')})
+ if form.accepted:
+ #remove the news
+ db(db.news.id==news.id).delete()
+ session.flash = T('News deleted')
+ redirect(URL('index'))
+ return dict(news=news, form=form)
+
+def rss_news():
+ newsS = db(db.news).select(orderby=~db.news.date|~db.news.published_on)
+ return dict(title=T('%s latest news',WEBSITE_PARAMETERS.website_name),
+ link=WEBSITE_PARAMETERS.website_url,
+ description=T('%s latest news',WEBSITE_PARAMETERS.website_name),
+ entries=[
+ dict(title=news.title,
+ link=WEBSITE_PARAMETERS.website_url,
+ created_on = news.published_on,
+ description=XML(news.text)) for news in newsS
+ ])
73 controllers/pages.py
@@ -0,0 +1,73 @@
+#from gluon.debug import dbg
+
+def show_page():
+ """
+ Show the requested page
+ """
+ manager_toolbar = ManagerToolbar('page')
+ if request.args(0).isdigit():
+ page = db.page(request.args(0))
+ else:
+ page = db(db.page.url==request.args(0)).select().first()
+
+ # if page: #set the "active" page in menu
+ # for index, menu in enumerate(response.menu):
+ # if menu[0]==page.title:
+ # is_enabled=True
+ # else:
+ # is_enabled=False
+ # response.menu[index]=menu[:1]+(is_enabled,)+menu[2:]
+ # else:
+ if not page:
+ if request.args(0).lower() == 'images':
+ redirect(URL('images'))
+ else:
+ page = db(db.page.is_index==True).select().first()
+
+ left_sidebar_component = db.page_component(page.left_sidebar_component)
+ right_sidebar_component = db.page_component(page.right_sidebar_component)
+ return dict(page=page,
+ left_sidebar_enabled=page.left_sidebar_enabled,
+ right_sidebar_enabled=page.right_sidebar_enabled,
+ left_sidebar_component=left_sidebar_component,
+ right_sidebar_component=right_sidebar_component,
+ manager_toolbar=manager_toolbar)
+
+@auth.requires_membership('manager')
+def delete_page():
+ if request.args(0).isdigit():
+ page = db.page(request.args(0))
+ else:
+ page = db(db.page.url==request.args(0)).select().first()
+ if len(request.args) and page:
+ form = FORM.confirm(T('Yes, I really want to delete this page'),{T('Back'):URL('show_page', args=page.id)})
+ if form.accepted:
+ #remove images linked to the page
+ pathname = os.path.join(request.folder,'static','images', 'pages_content', str(form.vars.id))
+ if os.path.exists(pathname):
+ shutil.rmtree(pathname)
+ #remove the page
+ db(db.page.id==page.id).delete()
+ session.flash = T('Page deleted')
+ redirect(URL('default', 'index'))
+ return dict(page=page, form=form)
+
+@auth.requires_membership('manager')
+def edit_page():
+ """
+ """
+ page_id = request.args(0)
+ if page_id:
+ if page_id.isdigit():
+ page = db.page(page_id)
+ else:
+ page = db(db.page.url==page_id).select().first()
+ if len(request.args) and page:
+ crud.settings.update_deletable = False
+ form = crud.update(db.page,page,next=URL('show_page', args=page.id))
+ else:
+ #Hide the "content" of the page : the page has no title
+ #and this is impossible to initialise the upload field with page.url
+ db.page.content.readable = db.page.content.writable = False
+ form = crud.create(db.page,next='edit_page/[id]')
+ return dict(form=form)
0  controllers/website_tools.py
No changes.
1  cron/crontab
@@ -0,0 +1 @@
+#crontab
1  cron/crontab.example
@@ -0,0 +1 @@
+#crontab
4 databases/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
4 errors/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
189 languages/cs.py
@@ -0,0 +1,189 @@
+# coding: utf8
+{
+'!langcode!': 'cs-cz',
+'!langname!': 'Český',
+'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" je voliteľný výraz ako "field1=\'newvalue\'". Nemôžete upravovať alebo zmazať výsledky JOINu',
+'%s %%{row} deleted': '%s zmazaných záznamů',
+'%s %%{row} updated': '%s upravených záznamů',
+'%s selected': '%s označených',
+'%Y-%m-%d': '%d.%m.%Y',
+'%Y-%m-%d %H:%M:%S': '%d.%m.%Y %H:%M:%S',
+'About': 'About',
+'Access Control': 'Access Control',
+'Administrative Interface': 'Administrative Interface',
+'Administrative interface': 'pro administrátorské rozhranie kliknite sem',
+'Ajax Recipes': 'Ajax Recipes',
+'appadmin is disabled because insecure channel': 'appadmin je zakázaný bez zabezpečeného spojení',
+'Are you sure you want to delete this object?': 'Opravdu chceš odstranit tento objekt?',
+'Available Databases and Tables': 'Dostupné databáze a tabuľky',
+'Buy this book': 'Buy this book',
+'cache': 'cache',
+'Cache': 'Cache',
+'Cache Keys': 'Cache Keys',
+'Cannot be empty': 'Nemůže být prázdné',
+'Change password': 'Změna hesla',
+'Check to delete': 'Označit ke smazání',
+'Check to delete:': 'Check to delete:',
+'Clear CACHE?': 'Clear CACHE?',
+'Clear DISK': 'Clear DISK',
+'Clear RAM': 'Clear RAM',
+'Client IP': 'Client IP',
+'Community': 'Community',
+'Components and Plugins': 'Components and Plugins',
+'Controller': 'Controller',
+'Copyright': 'Copyright',
+'Current request': 'Aktuální požadavek',
+'Current response': 'Aktuální odpověď',
+'Current session': 'Aktuální session',
+'customize me!': 'uprav mě!',
+'data uploaded': 'data nahrána',
+'Database': 'databáze',
+'Database %s select': 'databáze %s výber',
+'db': 'db',
+'DB Model': 'DB Model',
+'Delete:': 'Smazat:',
+'Demo': 'Demo',
+'Deployment Recipes': 'Deployment Recipes',
+'Description': 'Popis',
+'design': 'návrh',
+'DISK': 'DISK',
+'Disk Cache Keys': 'Disk Cache Keys',
+'Disk Cleared': 'Disk Cleared',
+'Documentation': 'Dokumentáce',
+"Don't know what to do?": "Don't know what to do?",
+'done!': 'hotovo!',
+'Download': 'Download',
+'E-mail': 'E-mail',
+'Edit': 'Upravit',
+'Edit current record': 'Upravit aktuální záznam',
+'Edit Profile': 'Upravit profil',
+'Email and SMS': 'Email and SMS',
+'enter a number between %(min)g and %(max)g': 'zadej číslo mezi %(min)g a %(max)g',
+'enter an integer between %(min)g and %(max)g': 'zadej celé číslo mezi %(min)g a %(max)g',
+'Errors': 'Errors',
+'export as csv file': 'exportovat do csv souboru',
+'FAQ': 'FAQ',
+'First name': 'Křestní jméno',
+'forgot username?': 'neznáš svúj nick?',
+'Forms and Validators': 'Forms and Validators',
+'Free Applications': 'Free Applications',
+'Group %(group_id)s created': 'Skupina %(group_id)s vytvořena',
+'Group ID': 'ID skupiny',
+'Groups': 'Groups',
+'Hello World': 'Ahoj světe',
+'Home': 'Home',
+'How did you get here?': 'How did you get here?',
+'import': 'import',
+'Import/Export': 'Import/Export',
+'Index': 'Index',
+'insert new': 'vložit nový záznam ',
+'insert new %s': 'vložit nový záznam %s',
+'Internal State': 'Vnitřní stav',
+'Introduction': 'Introduction',
+'Invalid email': 'Neplatný email',
+'Invalid password': 'Nesprávné heslo',
+'Invalid Query': 'Neplatná dotaz',
+'invalid request': 'Neplatný požadavek',
+'Key': 'Key',
+'Last name': 'Příjmení',
+'Layout': 'Layout',
+'Layout Plugins': 'Layout Plugins',
+'Layouts': 'Layouts',
+'Live Chat': 'Live Chat',
+'Logged in': 'Přihlášení úspěšné',
+'Logged out': 'Odhlášení úspěšné',
+'login': 'prihlásit',
+'Login': 'Login',
+'logout': 'odhlásit',
+'Lost Password': 'Ztracené heslo?',
+'lost password?': 'neznáš heslo?',
+'Manage Cache': 'Manage Cache',
+'Menu Model': 'Menu Model',
+'My Sites': 'My Sites',
+'Name': 'Jméno',
+'New password': 'Nové heslo',
+'New Record': 'Nový záznam',
+'new record inserted': 'nový záznam byl vložen',
+'next 100 rows': 'dalších 100 řádků',
+'No databases in this application': 'V této aplikáci nejsou databáze',
+'Object or table name': 'Objekt či tabulka',
+'Old password': 'Staré heslo',
+'Online examples': 'pro online příklady klikněte sem',
+'or import from csv file': 'a nebo naimportovat z csv souboru',
+'Origin': 'Púvod',
+'Other Plugins': 'Other Plugins',
+'Other Recipes': 'Other Recipes',
+'Overview': 'Overview',
+'password': 'heslo',
+'Password': 'Heslo',
+"Password fields don't match": 'Hesla se neshodují',
+'Plugins': 'Plugins',
+'Powered by': 'Powered by',
+'Preface': 'Preface',
+'previous 100 rows': 'předchádzajících 100 řádků',
+'profile': 'profil',
+'Python': 'Python',
+'Query:': 'Dotaz:',
+'Quick Examples': 'Quick Examples',
+'RAM': 'RAM',
+'RAM Cache Keys': 'RAM Cache Keys',
+'Ram Cleared': 'Ram Cleared',
+'Readme': 'Nápověda',
+'Recipes': 'Recipes',
+'Record': 'záznam',
+'record does not exist': 'záznam neexistuje',
+'Record ID': 'ID záznamu',
+'Record id': 'id záznamu',
+'Register': 'Zaregistrovat se',
+'register': 'registrovat',
+'Registration identifier': 'Registrační identifikátor',
+'Registration key': 'Registrační kľíč',
+'Remember me (for 30 days)': 'Zapamatuj si mne (na 30 dní)',
+'Reset Password key': 'Nastavit registrační kľíč',
+'Retrieve username': 'Retrieve username',
+'Role': 'Role',
+'Rows in Table': 'řádků v tabulce',
+'Rows selected': 'označených řádků',
+'Semantic': 'Semantic',
+'Services': 'Services',
+'Size of cache:': 'Size of cache:',
+'state': 'stav',
+'Statistics': 'Statistics',
+'Stylesheet': 'CSS',
+'submit': 'submit',
+'Submit': 'Odeslat',
+'Support': 'Support',
+'Sure you want to delete this object?': 'Opravdu chceš smazat tento objekt?',
+'Table': 'tabulka',
+'Table name': 'Název tabulky',
+'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"query" je podmínka jako "db.table1.field1==\'value\'". Něco jako "db.table1.field1==db.table2.field2" má za výsledek SQL JOIN.',
+'The Core': 'The Core',
+'The output of the file is a dictionary that was rendered by the view %s': 'Výstup zo souboru je slovník, ktorý byl zobrazený ve view %s',
+'The Views': 'The Views',
+'This App': 'This App',
+'This is a copy of the scaffolding application': 'Toto je kopie skeletu aplikace',
+'Time in Cache (h:m:s)': 'Time in Cache (h:m:s)',
+'Timestamp': 'Časové razítko',
+'Twitter': 'Twitter',
+'unable to parse csv file': 'nedá sa zpracovat csv soubor',
+'Update:': 'Upravit:',
+'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Použijte (...)&(...) pro AND, (...)|(...) pro OR a ~(...) pro NOT na poskládaní komplexnejších dotazů.',
+'User %(id)s Logged-in': 'Uživatel %(id)s prihlásen',
+'User %(id)s Logged-out': 'Uživatel %(id)s odhlášen',
+'User %(id)s Password changed': 'Uživatel %(id)s zmenil heslo',
+'User %(id)s Profile updated': 'Uživatel %(id)s upravil profil',
+'User %(id)s Registered': 'Uživatel %(id)s se zaregistroval',
+'User %(id)s Username retrieved': 'User %(id)s Username retrieved',
+'User ID': 'ID uživatele',
+'Username': 'Nick',
+'Verify Password': 'Zopakuj heslo',
+'Videos': 'Videos',
+'View': 'Zobrazit',
+'Welcome': 'Vítej',
+'Welcome to web2py': 'Vitejte ve web2py',
+'Welcome to web2py!': 'Welcome to web2py!',
+'Which called the function %s located in the file %s': 'Ktorý zavolal funkci %s v souboru %s',
+'You are successfully running web2py': 'Úspešně jste spustili web2py',
+'You can modify this application and adapt it to your needs': 'Můžete upravit tuto aplikáci a prispôsobit ji svojim potřebám',
+'You visited the url %s': 'Navštívili jste URL %s',
+}
122 languages/default.py
@@ -0,0 +1,122 @@
+# coding: utf8
+{
+'!langcode!': 'en-us',
+'!langname!': 'English (US)',
+'%s %%(shop)': '%s %%(shop)',
+'%s %%(shop[0])': '%s %%(shop[0])',
+'%s %%{quark[0]}': '%s %%{quark[0]}',
+'%s %%{shop[0]}': '%s %%{shop[0]}',
+'%s %%{shop}': '%s %%{shop}',
+'%Y-%m-%d': '%Y-%m-%d',
+'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
+'@markmin\x01**Hello World**': '**Hello World**',
+'About': 'About',
+'Access Control': 'Access Control',
+'Administrative Interface': 'Administrative Interface',
+'Ajax Recipes': 'Ajax Recipes',
+'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?',
+'Buy this book': 'Buy this book',
+'Cannot be empty': 'Cannot be empty',
+'Check to delete': 'Check to delete',
+'Client IP': 'Client IP',
+'Community': 'Community',
+'Components and Plugins': 'Components and Plugins',
+'Controller': 'Controller',
+'Copyright': 'Copyright',
+'Created By': 'Created By',
+'Created On': 'Created On',
+'customize me!': 'customize me!',
+'Database': 'Database',
+'DB Model': 'DB Model',
+'Demo': 'Demo',
+'Deployment Recipes': 'Deployment Recipes',
+'Description': 'Description',
+'Documentation': 'Documentation',
+"Don't know what to do?": "Don't know what to do?",
+'Download': 'Download',
+'E-mail': 'E-mail',
+'Email and SMS': 'Email and SMS',
+'enter an integer between %(min)g and %(max)g': 'enter an integer between %(min)g and %(max)g',
+'enter date and time as %(format)s': 'enter date and time as %(format)s',
+'Errors': 'Errors',
+'FAQ': 'FAQ',
+'First name': 'First name',
+'Forms and Validators': 'Forms and Validators',
+'Free Applications': 'Free Applications',
+'Group %(group_id)s created': 'Group %(group_id)s created',
+'Group ID': 'Group ID',
+'Group uniquely assigned to user %(id)s': 'Group uniquely assigned to user %(id)s',
+'Groups': 'Groups',
+'Hello World': 'Hello World',
+'Hello World ## comment': 'Hello World ',
+'Hello World## comment': 'Hello World',
+'Home': 'Home',
+'How did you get here?': 'How did you get here?',
+'Introduction': 'Introduction',
+'Invalid email': 'Invalid email',
+'Is Active': 'Is Active',
+'Last name': 'Last name',
+'Layout': 'Layout',
+'Layout Plugins': 'Layout Plugins',
+'Layouts': 'Layouts',
+'Live Chat': 'Live Chat',
+'Logged in': 'Logged in',
+'Logged out': 'Logged out',
+'Login': 'Login',
+'Logout': 'Logout',
+'Lost Password': 'Lost Password',
+'Lost password?': 'Lost password?',
+'Menu Model': 'Menu Model',
+'Modified By': 'Modified By',
+'Modified On': 'Modified On',
+'My Sites': 'My Sites',
+'Name': 'Name',
+'Object or table name': 'Object or table name',
+'Online examples': 'Online examples',
+'Origin': 'Origin',
+'Other Plugins': 'Other Plugins',
+'Other Recipes': 'Other Recipes',
+'Overview': 'Overview',
+'Password': 'Password',
+"Password fields don't match": "Password fields don't match",
+'please input your password again': 'please input your password again',
+'Plugins': 'Plugins',
+'Powered by': 'Powered by',
+'Preface': 'Preface',
+'Profile': 'Profile',
+'Python': 'Python',
+'Quick Examples': 'Quick Examples',
+'Recipes': 'Recipes',
+'Record ID': 'Record ID',
+'Register': 'Register',
+'Registration identifier': 'Registration identifier',
+'Registration key': 'Registration key',
+'Registration successful': 'Registration successful',
+'Remember me (for 30 days)': 'Remember me (for 30 days)',
+'Reset Password key': 'Reset Password key',
+'Role': 'Role',
+'Semantic': 'Semantic',
+'Services': 'Services',
+'Stylesheet': 'Stylesheet',
+'Support': 'Support',
+'The Core': 'The Core',
+'The output of the file is a dictionary that was rendered by the view %s': 'The output of the file is a dictionary that was rendered by the view %s',
+'The Views': 'The Views',
+'This App': 'This App',
+'Timestamp': 'Timestamp',
+'Twitter': 'Twitter',
+'User %(id)s Logged-in': 'User %(id)s Logged-in',
+'User %(id)s Logged-out': 'User %(id)s Logged-out',
+'User %(id)s Registered': 'User %(id)s Registered',
+'User ID': 'User ID',
+'value already in database or empty': 'value already in database or empty',
+'Verify Password': 'Verify Password',
+'Videos': 'Videos',
+'View': 'View',
+'Welcome': 'Welcome',
+'Welcome to web2py!': 'Welcome to web2py!',
+'Which called the function %s located in the file %s': 'Which called the function %s located in the file %s',
+'You are successfully running web2py': 'You are successfully running web2py',
+'You can modify this application and adapt it to your needs': 'You can modify this application and adapt it to your needs',
+'You visited the url %s': 'You visited the url %s',
+}
318 languages/es.py
@@ -0,0 +1,318 @@
+# coding: utf8
+{
+'!langcode!': 'es',
+'!langname!': 'Español',
+'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"actualice" es una expresión opcional como "campo1=\'nuevo_valor\'". No se puede actualizar o eliminar resultados de un JOIN',
+'%s %%{row} deleted': '%s filas eliminadas',
+'%s %%{row} updated': '%s filas actualizadas',
+'%s selected': '%s seleccionado(s)',
+'%Y-%m-%d': '%Y-%m-%d',
+'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
+'(something like "it-it")': '(algo como "it-it")',
+'A new version of web2py is available': 'Hay una nueva versión de web2py disponible',
+'A new version of web2py is available: %s': 'Hay una nueva versión de web2py disponible: %s',
+'about': 'acerca de',
+'About': 'Acerca de',
+'About application': 'Acerca de la aplicación',
+'Access Control': 'Access Control',
+'additional code for your application': 'código adicional para su aplicación',
+'admin disabled because no admin password': ' por falta de contraseña',
+'admin disabled because not supported on google app engine': 'admin deshabilitado, no es soportado en GAE',
+'admin disabled because unable to access password file': 'admin deshabilitado, imposible acceder al archivo con la contraseña',
+'Admin is disabled because insecure channel': 'Admin deshabilitado, el canal no es seguro',
+'Admin is disabled because unsecure channel': 'Admin deshabilitado, el canal no es seguro',
+'Administrative Interface': 'Administrative Interface',
+'Administrative interface': 'Interfaz administrativa',
+'Administrator Password:': 'Contraseña del Administrador:',
+'Ajax Recipes': 'Ajax Recipes',
+'and rename it (required):': 'y renombrela (requerido):',
+'and rename it:': ' y renombrelo:',
+'appadmin': 'appadmin',
+'appadmin is disabled because insecure channel': 'admin deshabilitado, el canal no es seguro',
+'application "%s" uninstalled': 'aplicación "%s" desinstalada',
+'application compiled': 'aplicación compilada',
+'application is compiled and cannot be designed': 'la aplicación está compilada y no puede ser modificada',
+'Are you sure you want to delete file "%s"?': '¿Está seguro que desea eliminar el archivo "%s"?',
+'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?',
+'Are you sure you want to uninstall application "%s"': '¿Está seguro que desea desinstalar la aplicación "%s"',
+'Are you sure you want to uninstall application "%s"?': '¿Está seguro que desea desinstalar la aplicación "%s"?',
+'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ATENCION: Inicio de sesión requiere una conexión segura (HTTPS) o localhost.',
+'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENCION: NO EJECUTE VARIAS PRUEBAS SIMULTANEAMENTE, NO SON THREAD SAFE.',
+'ATTENTION: you cannot edit the running application!': 'ATENCION: no puede modificar la aplicación que se ejecuta!',
+'Authentication': 'Autenticación',
+'Available Databases and Tables': 'Bases de datos y tablas disponibles',
+'Buy this book': 'Buy this book',
+'cache': 'cache',
+'Cache': 'Cache',
+'Cache Keys': 'Cache Keys',
+'cache, errors and sessions cleaned': 'cache, errores y sesiones eliminados',
+'Cannot be empty': 'No puede estar vacío',
+'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'No se puede compilar: hay errores en su aplicación. Depure, corrija errores y vuelva a intentarlo.',
+'cannot create file': 'no es posible crear archivo',
+'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"',
+'Change Password': 'Cambie Contraseña',
+'change password': 'cambie contraseña',
+'check all': 'marcar todos',
+'Check to delete': 'Marque para eliminar',
+'clean': 'limpiar',
+'Clear CACHE?': 'Clear CACHE?',
+'Clear DISK': 'Clear DISK',
+'Clear RAM': 'Clear RAM',
+'click to check for upgrades': 'haga clic para buscar actualizaciones',
+'Client IP': 'IP del Cliente',
+'Community': 'Community',
+'compile': 'compilar',
+'compiled application removed': 'aplicación compilada removida',
+'Components and Plugins': 'Components and Plugins',
+'Controller': 'Controlador',
+'Controllers': 'Controladores',
+'controllers': 'controladores',
+'Copyright': 'Derechos de autor',
+'create file with filename:': 'cree archivo con nombre:',
+'Create new application': 'Cree una nueva aplicación',
+'create new application:': 'nombre de la nueva aplicación:',
+'crontab': 'crontab',
+'Current request': 'Solicitud en curso',
+'Current response': 'Respuesta en curso',
+'Current session': 'Sesión en curso',
+'currently saved or': 'actualmente guardado o',
+'customize me!': 'Adaptame!',
+'data uploaded': 'datos subidos',
+'Database': 'base de datos',
+'Database %s select': 'selección en base de datos %s',
+'database administration': 'administración base de datos',
+'Date and Time': 'Fecha y Hora',
+'db': 'db',
+'DB Model': 'Modelo "db"',
+'defines tables': 'define tablas',
+'Delete': 'Elimine',
+'delete': 'eliminar',
+'delete all checked': 'eliminar marcados',
+'Delete:': 'Elimine:',
+'Demo': 'Demo',
+'Deploy on Google App Engine': 'Instale en Google App Engine',
+'Deployment Recipes': 'Deployment Recipes',
+'Description': 'Descripción',
+'DESIGN': 'DISEÑO',
+'design': 'modificar',
+'Design for': 'Diseño para',
+'DISK': 'DISK',
+'Disk Cache Keys': 'Disk Cache Keys',
+'Disk Cleared': 'Disk Cleared',
+'Documentation': 'Documentación',
+"Don't know what to do?": "Don't know what to do?",
+'done!': 'listo!',
+'Download': 'Download',
+'E-mail': 'Correo electrónico',
+'EDIT': 'EDITAR',
+'edit': 'editar',
+'Edit': 'Editar',
+'Edit application': 'Editar aplicación',
+'edit controller': 'editar controlador',
+'Edit current record': 'Edite el registro actual',
+'edit profile': 'editar perfil',
+'Edit Profile': 'Editar Perfil',
+'Edit This App': 'Edite esta App',
+'Editing file': 'Editando archivo',
+'Editing file "%s"': 'Editando archivo "%s"',
+'Email and SMS': 'Email and SMS',
+'Error logs for "%(app)s"': 'Bitácora de errores en "%(app)s"',
+'Errors': 'Errors',
+'errors': 'errores',
+'export as csv file': 'exportar como archivo CSV',
+'exposes': 'expone',
+'extends': 'extiende',
+'failed to reload module': 'recarga del módulo ha fallado',
+'FAQ': 'FAQ',
+'file "%(filename)s" created': 'archivo "%(filename)s" creado',
+'file "%(filename)s" deleted': 'archivo "%(filename)s" eliminado',
+'file "%(filename)s" uploaded': 'archivo "%(filename)s" subido',
+'file "%(filename)s" was not deleted': 'archivo "%(filename)s" no fué eliminado',
+'file "%s" of %s restored': 'archivo "%s" de %s restaurado',
+'file changed on disk': 'archivo modificado en el disco',
+'file does not exist': 'archivo no existe',
+'file saved on %(time)s': 'archivo guardado %(time)s',
+'file saved on %s': 'archivo guardado %s',
+'First name': 'Nombre',
+'Forms and Validators': 'Forms and Validators',
+'Free Applications': 'Free Applications',
+'Functions with no doctests will result in [passed] tests.': 'Funciones sin doctests equivalen a pruebas [aceptadas].',
+'Group ID': 'ID de Grupo',
+'Groups': 'Groups',
+'Hello World': 'Hola Mundo',
+'help': 'ayuda',
+'Home': 'Home',
+'How did you get here?': 'How did you get here?',
+'htmledit': 'htmledit',
+'import': 'import',
+'Import/Export': 'Importar/Exportar',
+'includes': 'incluye',
+'Index': 'Indice',
+'insert new': 'inserte nuevo',
+'insert new %s': 'inserte nuevo %s',
+'Installed applications': 'Aplicaciones instaladas',
+'internal error': 'error interno',
+'Internal State': 'Estado Interno',
+'Introduction': 'Introduction',
+'Invalid action': 'Acción inválida',
+'Invalid email': 'Correo inválido',
+'invalid password': 'contraseña inválida',
+'Invalid Query': 'Consulta inválida',
+'invalid request': 'solicitud inválida',
+'invalid ticket': 'tiquete inválido',
+'Key': 'Key',
+'language file "%(filename)s" created/updated': 'archivo de lenguaje "%(filename)s" creado/actualizado',
+'Language files (static strings) updated': 'Archivos de lenguaje (cadenas estáticas) actualizados',
+'languages': 'lenguajes',
+'Languages': 'Lenguajes',
+'languages updated': 'lenguajes actualizados',
+'Last name': 'Apellido',
+'Last saved on:': 'Guardado en:',
+'Layout': 'Diseño de página',
+'Layout Plugins': 'Layout Plugins',
+'Layouts': 'Layouts',
+'License for': 'Licencia para',
+'Live Chat': 'Live Chat',
+'loading...': 'cargando...',
+'login': 'inicio de sesión',
+'Login': 'Inicio de sesión',
+'Login to the Administrative Interface': 'Inicio de sesión para la Interfaz Administrativa',
+'logout': 'fin de sesión',
+'Logout': 'Fin de sesión',
+'Lost Password': 'Contraseña perdida',
+'lost password?': '¿olvido la contraseña?',
+'Main Menu': 'Menú principal',
+'Manage Cache': 'Manage Cache',
+'Menu Model': 'Modelo "menu"',
+'merge': 'combinar',
+'Models': 'Modelos',
+'models': 'modelos',
+'Modules': 'Módulos',
+'modules': 'módulos',
+'My Sites': 'My Sites',
+'Name': 'Nombre',
+'new application "%s" created': 'nueva aplicación "%s" creada',
+'New Record': 'Registro nuevo',
+'new record inserted': 'nuevo registro insertado',
+'next 100 rows': '100 filas siguientes',
+'NO': 'NO',
+'No databases in this application': 'No hay bases de datos en esta aplicación',
+'Online examples': 'Ejemplos en línea',
+'or import from csv file': 'o importar desde archivo CSV',
+'or provide application url:': 'o provea URL de la aplicación:',
+'Origin': 'Origen',
+'Original/Translation': 'Original/Traducción',
+'Other Plugins': 'Other Plugins',
+'Other Recipes': 'Other Recipes',
+'Overview': 'Overview',
+'pack all': 'empaquetar todo',
+'pack compiled': 'empaquete compiladas',
+'Password': 'Contraseña',
+'Peeking at file': 'Visualizando archivo',
+'Plugins': 'Plugins',
+'Powered by': 'Este sitio usa',
+'Preface': 'Preface',
+'previous 100 rows': '100 filas anteriores',
+'Python': 'Python',
+'Query:': 'Consulta:',
+'Quick Examples': 'Quick Examples',
+'RAM': 'RAM',
+'RAM Cache Keys': 'RAM Cache Keys',
+'Ram Cleared': 'Ram Cleared',
+'Recipes': 'Recipes',
+'Record': 'registro',
+'record does not exist': 'el registro no existe',
+'Record ID': 'ID de Registro',
+'Record id': 'id de registro',
+'Register': 'Registrese',
+'register': 'registrese',
+'Registration key': 'Contraseña de Registro',
+'remove compiled': 'eliminar compiladas',
+'Reset Password key': 'Reset Password key',
+'Resolve Conflict file': 'archivo Resolución de Conflicto',
+'restore': 'restaurar',
+'revert': 'revertir',
+'Role': 'Rol',
+'Rows in Table': 'Filas en la tabla',
+'Rows selected': 'Filas seleccionadas',
+'save': 'guardar',
+'Saved file hash:': 'Hash del archivo guardado:',
+'Semantic': 'Semantic',
+'Services': 'Services',
+'session expired': 'sesión expirada',
+'shell': 'shell',
+'site': 'sitio',
+'Size of cache:': 'Size of cache:',
+'some files could not be removed': 'algunos archivos no pudieron ser removidos',
+'state': 'estado',
+'static': 'estáticos',
+'Static files': 'Archivos estáticos',
+'Statistics': 'Statistics',
+'Stylesheet': 'Hoja de estilo',
+'submit': 'submit',
+'Support': 'Support',
+'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?',
+'Table': 'tabla',
+'Table name': 'Nombre de la tabla',
+'test': 'probar',
+'Testing application': 'Probando aplicación',
+'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La "consulta" es una condición como "db.tabla1.campo1==\'valor\'". Algo como "db.tabla1.campo1==db.tabla2.campo2" resulta en un JOIN SQL.',
+'the application logic, each URL path is mapped in one exposed function in the controller': 'la lógica de la aplicación, cada ruta URL se mapea en una función expuesta en el controlador',
+'The Core': 'The Core',
+'the data representation, define database tables and sets': 'la representación de datos, define tablas y conjuntos de base de datos',
+'The output of the file is a dictionary that was rendered by the view %s': 'La salida del archivo es un diccionario escenificado por la vista %s',
+'the presentations layer, views are also known as templates': 'la capa de presentación, las vistas también son llamadas plantillas',
+'The Views': 'The Views',
+'There are no controllers': 'No hay controladores',
+'There are no models': 'No hay modelos',
+'There are no modules': 'No hay módulos',
+'There are no static files': 'No hay archivos estáticos',
+'There are no translators, only default language is supported': 'No hay traductores, sólo el lenguaje por defecto es soportado',
+'There are no views': 'No hay vistas',
+'these files are served without processing, your images go here': 'estos archivos son servidos sin procesar, sus imágenes van aquí',
+'This App': 'This App',
+'This is a copy of the scaffolding application': 'Esta es una copia de la aplicación de andamiaje',
+'This is the %(filename)s template': 'Esta es la plantilla %(filename)s',
+'Ticket': 'Tiquete',
+'Time in Cache (h:m:s)': 'Time in Cache (h:m:s)',
+'Timestamp': 'Timestamp',
+'to previous version.': 'a la versión previa.',
+'translation strings for the application': 'cadenas de caracteres de traducción para la aplicación',
+'try': 'intente',
+'try something like': 'intente algo como',
+'Twitter': 'Twitter',
+'Unable to check for upgrades': 'No es posible verificar la existencia de actualizaciones',
+'unable to create application "%s"': 'no es posible crear la aplicación "%s"',
+'unable to delete file "%(filename)s"': 'no es posible eliminar el archivo "%(filename)s"',
+'Unable to download': 'No es posible la descarga',
+'Unable to download app': 'No es posible descarga la aplicación',
+'unable to parse csv file': 'no es posible analizar el archivo CSV',
+'unable to uninstall "%s"': 'no es posible instalar "%s"',
+'uncheck all': 'desmarcar todos',
+'uninstall': 'desinstalar',
+'update': 'actualizar',
+'update all languages': 'actualizar todos los lenguajes',
+'Update:': 'Actualice:',
+'upload application:': 'subir aplicación:',
+'Upload existing application': 'Suba esta aplicación',
+'upload file:': 'suba archivo:',
+'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, y ~(...) para NOT, para crear consultas más complejas.',
+'User ID': 'ID de Usuario',
+'versioning': 'versiones',
+'Videos': 'Videos',
+'view': 'vista',
+'View': 'Vista',
+'Views': 'Vistas',
+'views': 'vistas',
+'web2py is up to date': 'web2py está actualizado',
+'web2py Recent Tweets': 'Tweets Recientes de web2py',
+'Welcome': 'Welcome',
+'Welcome %s': 'Bienvenido %s',
+'Welcome to web2py': 'Bienvenido a web2py',
+'Welcome to web2py!': 'Welcome to web2py!',
+'Which called the function %s located in the file %s': 'La cual llamó la función %s localizada en el archivo %s',
+'YES': 'SI',
+'You are successfully running web2py': 'Usted está ejecutando web2py exitosamente',
+'You can modify this application and adapt it to your needs': 'Usted puede modificar esta aplicación y adaptarla a sus necesidades',
+'You visited the url %s': 'Usted visitó la url %s',
+}
195 languages/fr-ca.py
@@ -0,0 +1,195 @@
+# coding: utf8
+{
+'!langcode!': 'fr-ca',
+'!langname!': 'Français (Canadien)',
+'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" est une expression optionnelle comme "champ1=\'nouvellevaleur\'". Vous ne pouvez mettre à jour ou supprimer les résultats d\'un JOIN',
+'%s %%{row} deleted': '%s rangées supprimées',
+'%s %%{row} updated': '%s rangées mises à jour',
+'%s selected': '%s sélectionné',
+'%Y-%m-%d': '%Y-%m-%d',
+'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
+'about': 'à propos',
+'About': 'À propos',
+'Access Control': "Contrôle d'accès",
+'Administrative Interface': 'Administrative Interface',
+'Administrative interface': "Interface d'administration",
+'Ajax Recipes': 'Recettes Ajax',
+'appadmin is disabled because insecure channel': "appadmin est désactivée parce que le canal n'est pas sécurisé",
+'Are you sure you want to delete this object?': 'Êtes-vous sûr de vouloir supprimer cet objet?',
+'Authentication': 'Authentification',
+'Available Databases and Tables': 'Bases de données et tables disponibles',
+'Buy this book': 'Acheter ce livre',
+'cache': 'cache',
+'Cache': 'Cache',
+'Cache Keys': 'Cache Keys',
+'Cannot be empty': 'Ne peut pas être vide',
+'change password': 'changer le mot de passe',
+'Check to delete': 'Cliquez pour supprimer',
+'Check to delete:': 'Cliquez pour supprimer:',
+'Clear CACHE?': 'Clear CACHE?',
+'Clear DISK': 'Clear DISK',
+'Clear RAM': 'Clear RAM',
+'Client IP': 'IP client',
+'Community': 'Communauté',
+'Components and Plugins': 'Components and Plugins',
+'Controller': 'Contrôleur',
+'Copyright': "Droit d'auteur",
+'Current request': 'Demande actuelle',
+'Current response': 'Réponse actuelle',
+'Current session': 'Session en cours',
+'customize me!': 'personnalisez-moi!',
+'data uploaded': 'données téléchargées',
+'Database': 'base de données',
+'Database %s select': 'base de données %s select',
+'db': 'db',
+'DB Model': 'Modèle DB',
+'Delete:': 'Supprimer:',
+'Demo': 'Démo',
+'Deployment Recipes': 'Recettes de déploiement ',
+'Description': 'Descriptif',
+'design': 'design',
+'DISK': 'DISK',
+'Disk Cache Keys': 'Disk Cache Keys',
+'Disk Cleared': 'Disk Cleared',
+'Documentation': 'Documentation',
+"Don't know what to do?": "Don't know what to do?",
+'done!': 'fait!',
+'Download': 'Téléchargement',
+'E-mail': 'Courriel',
+'Edit': 'Éditer',
+'Edit current record': "Modifier l'enregistrement courant",
+'edit profile': 'modifier le profil',
+'Edit This App': 'Modifier cette application',
+'Email and SMS': 'Email and SMS',
+'enter an integer between %(min)g and %(max)g': 'entrer un entier compris entre %(min)g et %(max)g',
+'Errors': 'Erreurs',
+'export as csv file': 'exporter sous forme de fichier csv',
+'FAQ': 'faq',
+'First name': 'Prénom',
+'Forms and Validators': 'Formulaires et Validateurs',
+'Free Applications': 'Applications gratuites',
+'Function disabled': 'Fonction désactivée',
+'Group %(group_id)s created': '%(group_id)s groupe créé',
+'Group ID': 'Groupe ID',
+'Group uniquely assigned to user %(id)s': "Groupe unique attribué à l'utilisateur %(id)s",
+'Groups': 'Groupes',
+'Hello World': 'Bonjour le monde',
+'Home': 'Accueil',
+'How did you get here?': 'How did you get here?',
+'import': 'import',
+'Import/Export': 'Importer/Exporter',
+'Index': 'Index',
+'insert new': 'insérer un nouveau',
+'insert new %s': 'insérer un nouveau %s',
+'Internal State': 'État interne',
+'Introduction': 'Présentation',
+'Invalid email': 'Courriel invalide',
+'Invalid Query': 'Requête Invalide',
+'invalid request': 'requête invalide',
+'Key': 'Key',
+'Last name': 'Nom',
+'Layout': 'Mise en page',
+'Layout Plugins': 'Layout Plugins',
+'Layouts': 'layouts',
+'Live chat': 'Clavardage en direct',
+'Live Chat': 'Live Chat',
+'Logged in': 'Connecté',
+'login': 'connectez-vous',
+'Login': 'Connectez-vous',
+'logout': 'déconnectez-vous',
+'lost password': 'mot de passe perdu',
+'Lost Password': 'Mot de passe perdu',
+'lost password?': 'mot de passe perdu?',
+'Main Menu': 'Menu principal',
+'Manage Cache': 'Manage Cache',
+'Menu Model': 'Menu modèle',
+'My Sites': 'My Sites',
+'Name': 'Nom',
+'New Record': 'Nouvel enregistrement',
+'new record inserted': 'nouvel enregistrement inséré',
+'next 100 rows': '100 prochaines lignes',
+'No databases in this application': "Cette application n'a pas de bases de données",
+'Online examples': 'Exemples en ligne',
+'or import from csv file': "ou importer d'un fichier CSV",
+'Origin': 'Origine',
+'Other Plugins': 'Other Plugins',
+'Other Recipes': 'Autres recettes',
+'Overview': 'Présentation',
+'password': 'mot de passe',
+'Password': 'Mot de passe',
+"Password fields don't match": 'Les mots de passe ne correspondent pas',
+'please input your password again': "S'il vous plaît entrer votre mot de passe",
+'Plugins': 'Plugiciels',
+'Powered by': 'Alimenté par',
+'Preface': 'Préface',
+'previous 100 rows': '100 lignes précédentes',
+'profile': 'profile',
+'Python': 'Python',
+'Query:': 'Requête:',
+'Quick Examples': 'Examples Rapides',
+'RAM': 'RAM',
+'RAM Cache Keys': 'RAM Cache Keys',
+'Ram Cleared': 'Ram Cleared',
+'Readme': 'Lisez-moi',
+'Recipes': 'Recettes',
+'Record': 'enregistrement',
+'Record %(id)s created': 'Record %(id)s created',
+'Record %(id)s updated': 'Record %(id)s updated',
+'Record Created': 'Record Created',
+'record does not exist': "l'archive n'existe pas",
+'Record ID': "ID d'enregistrement",
+'Record id': "id d'enregistrement",
+'Record Updated': 'Record Updated',
+'Register': "S'inscrire",
+'register': "s'inscrire",
+'Registration key': "Clé d'enregistrement",
+'Registration successful': 'Inscription réussie',
+'Remember me (for 30 days)': 'Se souvenir de moi (pendant 30 jours)',
+'Request reset password': 'Demande de réinitialiser le mot clé',
+'Reset Password key': 'Réinitialiser le mot clé',
+'Resources': 'Ressources',
+'Role': 'Rôle',
+'Rows in Table': 'Lignes du tableau',
+'Rows selected': 'Lignes sélectionnées',
+'Semantic': 'Sémantique',
+'Services': 'Services',
+'Size of cache:': 'Size of cache:',
+'state': 'état',
+'Statistics': 'Statistics',
+'Stylesheet': 'Feuille de style',
+'submit': 'submit',
+'Submit': 'Soumettre',
+'Support': 'Soutien',
+'Sure you want to delete this object?': 'Êtes-vous sûr de vouloir supprimer cet objet?',
+'Table': 'tableau',
+'Table name': 'Nom du tableau',
+'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La "query" est une condition comme "db.table1.champ1==\'valeur\'". Quelque chose comme "db.table1.champ1==db.table2.champ2" résulte en un JOIN SQL.',
+'The Core': 'Le noyau',
+'The output of the file is a dictionary that was rendered by the view %s': 'La sortie de ce fichier est un dictionnaire qui été restitué par la vue %s',
+'The Views': 'Les Vues',
+'This App': 'Cette Appli',
+'This is a copy of the scaffolding application': "Ceci est une copie de l'application échafaudage",
+'Time in Cache (h:m:s)': 'Time in Cache (h:m:s)',
+'Timestamp': 'Horodatage',
+'Twitter': 'Twitter',
+'unable to parse csv file': "incapable d'analyser le fichier cvs",
+'Update:': 'Mise à jour:',
+'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Employez (...)&(...) pour AND, (...)|(...) pour OR, and ~(...) pour NOT pour construire des requêtes plus complexes.',
+'User %(id)s Logged-in': 'Utilisateur %(id)s connecté',
+'User %(id)s Registered': 'Utilisateur %(id)s enregistré',
+'User ID': 'ID utilisateur',
+'User Voice': 'User Voice',
+'value already in database or empty': 'valeur déjà dans la base ou vide',
+'Verify Password': 'Vérifiez le mot de passe',
+'Videos': 'Vidéos',
+'View': 'Présentation',
+'Web2py': 'Web2py',
+'Welcome': 'Bienvenu',
+'Welcome %s': 'Bienvenue %s',
+'Welcome to web2py': 'Bienvenue à web2py',
+'Welcome to web2py!': 'Welcome to web2py!',
+'Which called the function %s located in the file %s': 'Qui a appelé la fonction %s se trouvant dans le fichier %s',
+'You are successfully running web2py': 'Vous roulez avec succès web2py',
+'You can modify this application and adapt it to your needs': "Vous pouvez modifier cette application et l'adapter à vos besoins",
+'You visited the url %s': "Vous avez visité l'URL %s",
+}
449 languages/fr.py
@@ -0,0 +1,449 @@
+# coding: utf8
+{
+'\n Name : %s\n Email : %s\n Subject : %s\n Message : %s\n ': ' Nom : %s\r\n E-mail : %s\r\n Sujet: %s\r\n Message : %s\r\n ',
+'\n The following person would like to book %s :\n\n Name : %s\n Email : %s\n Phone number : %s\n Address : %s\n From : %s\n During : %s\n ': ' La personne suivante aimerait réserver %s :\r\n\r\n Nom : %s\r\n E-mail : %s\r\n Téléphone : %s\r\n Adresse : %s\r\n A partir de : %s\r\n Durée : %s\r\n ',
+'\n The following person would like to book %s :\n\n Name : %s\n Email : %s\n Phone number : %s\n Address : %s\n Start date : %s at %s\n End date : %s at %s\n ': ' La personne suivante aimerait réserver %s :\r\n\r\n Nom : %s\r\n E-mail : %s\r\n Téléphone : %s\r\n Adresse : %s\r\n Du : %s à %s\r\n Au : %s à %s\r\n ',
+'!=': '!=',
+'!langcode!': 'fr',
+'!langname!': 'Français',
+'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" est une expression optionnelle comme "champ1=\'nouvellevaleur\'". Vous ne pouvez mettre à jour ou supprimer les résultats d\'un JOIN',
+'%(nrows)s records found': '%(nrows)s enregistrements trouvés',
+'%s %%{row} deleted': '%s rangées supprimées',
+'%s %%{row} updated': '%s rangées mises à jour',
+'%s selected': '%s sélectionné',
+'%Y-%m-%d': '%d/%m/%Y',
+'%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S',
+'<': '<',
+'<=': '<=',
+'<Empty>': '<Aucun>',
+'=': '=',
+'>': '>',
+'>=': '>=',
+'About': 'À propos',
+'Access Control': "Contrôle d'accès",
+'Add': 'Ajouter',
+'Add a file': 'Ajouter un fichier',
+'Add a new %(object)s': 'Ajouter un objet %(object)s',
+'Add a new page': 'Ajouter une page',
+'Add a news': 'Ajouter une actualité',
+'Add image in the Gallery': 'Ajouter une image dans la galerie',
+'Add new image': 'Ajouter une image',
+'Add news': 'Ajouter une actualité',
+'Address': 'Adresse',
+'Administrative interface': "Interface d'administration",
+'Administrative Interface': "Interface d'Administration",
+'Ajax Recipes': 'Recettes Ajax',
+'Alt': 'Texte alternatif',
+'And': 'Et',
+'appadmin is disabled because insecure channel': "appadmin est désactivée parce que le canal n'est pas sécurisé",
+'Apr': 'Avr',
+'April': 'Avril',
+'Are you sure you want to delete this object?': 'Êtes-vous sûr de vouloir supprimer cet objet?',
+'Aug': 'Août',
+'August': 'Août',
+'Authentication': 'Authentification',
+'Available Databases and Tables': 'Bases de données et tables disponibles',
+'Back': 'Retour',
+'booked': 'réservé',
+'booked during %s': 'réservé pour %s',
+'Booking form cc': 'Formulaire de réservation cc',
+'Booking form cci': 'Formulaire de réservation cci',
+'Booking form email': 'Formulaire de réservation email',
+'Booking request': 'Demande de réservation',
+'Booking request for %s on %s website': 'Demande de réservation pour %s on le site %s',
+'Booking requests': 'Demandes de réservation',
+'Buy this book': 'Acheter ce livre',
+'bytes': 'octetc',
+'cache': 'cache',
+'Cache Keys': 'Index de cache',
+'Calendar booking': 'Demande de réservation',
+'Calendar events': 'Calendrier',
+'CANCELLED': 'ANNULÉ',
+'Cannot be empty': 'Ne peut pas être vide',
+'Change password': 'Changer le mot de passe',
+'change password': 'changer le mot de passe',
+'Check to delete': 'Cliquez pour supprimer',
+<