mirror of https://github.com/apache/superset.git
Getting started on translations (#423)
This commit is contained in:
parent
ec7dbed800
commit
88c9516e20
|
@ -1,6 +1,5 @@
|
||||||
*.pyc
|
*.pyc
|
||||||
changelog.sh
|
changelog.sh
|
||||||
babel
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.coverage
|
.coverage
|
||||||
_build
|
_build
|
||||||
|
|
|
@ -159,12 +159,12 @@ Generate the documentation with:
|
||||||
cd docs && ./build.sh
|
cd docs && ./build.sh
|
||||||
|
|
||||||
## CSS Themes
|
## CSS Themes
|
||||||
As part of the npm build process, CSS for Caravel is compiled from ```Less```, a dynamic stylesheet language.
|
As part of the npm build process, CSS for Caravel is compiled from `Less`, a dynamic stylesheet language.
|
||||||
|
|
||||||
It's possible to customize or add your own theme to Caravel, either by overriding CSS rules or preferably
|
It's possible to customize or add your own theme to Caravel, either by overriding CSS rules or preferably
|
||||||
by modifying the Less variables or files in ```assets/stylesheets/less/```.
|
by modifying the Less variables or files in `assets/stylesheets/less/`.
|
||||||
|
|
||||||
The ```variables.less``` and ```bootswatch.less``` files that ship with Caravel are derived from
|
The `variables.less` and `bootswatch.less` files that ship with Caravel are derived from
|
||||||
[Bootswatch](https://bootswatch.com) and thus extend Bootstrap. Modify variables in these files directly, or
|
[Bootswatch](https://bootswatch.com) and thus extend Bootstrap. Modify variables in these files directly, or
|
||||||
swap them out entirely with the equivalent files from other Bootswatch (themes)[https://github.com/thomaspark/bootswatch.git]
|
swap them out entirely with the equivalent files from other Bootswatch (themes)[https://github.com/thomaspark/bootswatch.git]
|
||||||
|
|
||||||
|
@ -179,7 +179,43 @@ meets these guidelines:
|
||||||
as part of the same PR. Doc string are often sufficient, make
|
as part of the same PR. Doc string are often sufficient, make
|
||||||
sure to follow the sphinx compatible standards.
|
sure to follow the sphinx compatible standards.
|
||||||
3. The pull request should work for Python 2.6, 2.7, and ideally python 3.3.
|
3. The pull request should work for Python 2.6, 2.7, and ideally python 3.3.
|
||||||
`from __future__ import ` will be required in every `.py` file soon.
|
``from __future__ import`` will be required in every `.py` file soon.
|
||||||
4. Code will be reviewed by re running the unittests, flake8 and syntax
|
4. Code will be reviewed by re running the unittests, flake8 and syntax
|
||||||
should be as rigorous as the core Python project.
|
should be as rigorous as the core Python project.
|
||||||
5. Please rebase and resolve all conflicts before submitting.
|
5. Please rebase and resolve all conflicts before submitting.
|
||||||
|
|
||||||
|
|
||||||
|
## Tranlations
|
||||||
|
|
||||||
|
We use [Babel](http://babel.pocoo.org/en/latest/) to translate Caravel. The
|
||||||
|
key is to instrument the strings that need translation using
|
||||||
|
`from flask.ext.babelpkg import lazy_gettext as _`. Once this is imported in
|
||||||
|
a module, all you have to do is to `_("Wrap your strings")` using the
|
||||||
|
underscore `_` "function".
|
||||||
|
|
||||||
|
To enable changing language in your environment, you can simply add the
|
||||||
|
`LANGUAGES` parameter to your `caravel_config.py`. Having more than one
|
||||||
|
options here will add a language selection dropdown on the right side of the
|
||||||
|
navigation bar.
|
||||||
|
|
||||||
|
LANGUAGES = {
|
||||||
|
'en': {'flag': 'us', 'name': 'English'},
|
||||||
|
'fr': {'flag': 'fr', 'name': 'French'},
|
||||||
|
'zh': {'flag': 'cn', 'name': 'Chinese'},
|
||||||
|
}
|
||||||
|
|
||||||
|
As per the [Flask AppBuilder documentation] about translation, to create a
|
||||||
|
new language dictionary, run the following command:
|
||||||
|
|
||||||
|
pybabel init -i ./babel/messages.pot -d caravel/translations -l es
|
||||||
|
|
||||||
|
Then it's a matter of running the statement bellow to gather all stings that
|
||||||
|
need translation
|
||||||
|
|
||||||
|
fabmanager babel-extract --target caravel/translations/
|
||||||
|
|
||||||
|
You can then translate the strings gathered in files located under
|
||||||
|
`caravel/translation`, where there's one per language. For the translations
|
||||||
|
to take effect, they need to be compiled using this command:
|
||||||
|
|
||||||
|
fabmanager babel-compile --target caravel/translations/
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[ignore: caravel/assets/node_modules/**]
|
||||||
|
[python: caravel/**.py]
|
||||||
|
[jinja2: caravel/**/templates/**.html]
|
||||||
|
encoding = utf-8
|
|
@ -0,0 +1,117 @@
|
||||||
|
# Translations template for Caravel.
|
||||||
|
# Copyright (C) 2016 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the Caravel project.
|
||||||
|
# Maxime Beauchemin <maximebeauchemin @ gmail.com>, 2016.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2016-05-02 00:21-0700\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: Babel 2.3.4\n"
|
||||||
|
|
||||||
|
#: caravel/models.py:564
|
||||||
|
msgid ""
|
||||||
|
"Datetime column not provided as part table configuration and is required "
|
||||||
|
"by this type of chart"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/models.py:1153
|
||||||
|
msgid "No data was returned."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:116
|
||||||
|
msgid ""
|
||||||
|
"Whether to make this column available as a [Time Granularity] option, "
|
||||||
|
"column has to be DATETIME or DATETIME-like"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:215
|
||||||
|
msgid "Databases"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:217 caravel/views.py:261 caravel/views.py:284
|
||||||
|
msgid "Sources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:260
|
||||||
|
msgid "Tables"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:282
|
||||||
|
msgid "Druid Clusters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:313
|
||||||
|
msgid "Slices"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:341
|
||||||
|
msgid ""
|
||||||
|
"This json object describes the positioning of the widgets in the "
|
||||||
|
"dashboard. It is dynamically generated when adjusting the widgets size "
|
||||||
|
"and positions by using drag & drop in the dashboard view"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:346
|
||||||
|
msgid ""
|
||||||
|
"The css for individual dashboards can be altered here, or in the "
|
||||||
|
"dashboard view where changes are immediately visible"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:367
|
||||||
|
msgid "Dashboards"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:392
|
||||||
|
msgid "Action Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:393
|
||||||
|
msgid "Security"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:430
|
||||||
|
msgid "Druid Datasources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:514
|
||||||
|
msgid "The datasource seems to have been deleted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:522
|
||||||
|
msgid "You don't seem to have access to this datasource"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:843
|
||||||
|
msgid "This view requires the `all_datasource_access` permission"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:954
|
||||||
|
msgid "CSS Templates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:34
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:35
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:40
|
||||||
|
msgid "Login"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/caravel/welcome.html:8
|
||||||
|
#: caravel/templates/caravel/welcome.html:13
|
||||||
|
msgid "Welcome!"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -2,6 +2,10 @@ body {
|
||||||
margin: 0px !important;
|
margin: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.caret {
|
||||||
|
border-top: 4px solid;
|
||||||
|
}
|
||||||
|
|
||||||
.emph {
|
.emph {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,10 +99,12 @@ AUTH_TYPE = AUTH_DB
|
||||||
# Setup default language
|
# Setup default language
|
||||||
BABEL_DEFAULT_LOCALE = 'en'
|
BABEL_DEFAULT_LOCALE = 'en'
|
||||||
# Your application default translation path
|
# Your application default translation path
|
||||||
BABEL_DEFAULT_FOLDER = 'translations'
|
BABEL_DEFAULT_FOLDER = 'babel/translations'
|
||||||
# The allowed translation for you app
|
# The allowed translation for you app
|
||||||
LANGUAGES = {
|
LANGUAGES = {
|
||||||
'en': {'flag': 'us', 'name': 'English'},
|
'en': {'flag': 'us', 'name': 'English'},
|
||||||
|
# 'fr': {'flag': 'fr', 'name': 'French'},
|
||||||
|
# 'zh': {'flag': 'cn', 'name': 'Chinese'},
|
||||||
}
|
}
|
||||||
# ---------------------------------------------------
|
# ---------------------------------------------------
|
||||||
# Image and file configuration
|
# Image and file configuration
|
||||||
|
|
|
@ -18,11 +18,14 @@ import requests
|
||||||
import sqlalchemy as sqla
|
import sqlalchemy as sqla
|
||||||
import sqlparse
|
import sqlparse
|
||||||
from dateutil.parser import parse
|
from dateutil.parser import parse
|
||||||
|
|
||||||
from flask import request, g
|
from flask import request, g
|
||||||
from flask.ext.appbuilder import Model
|
from flask.ext.appbuilder import Model
|
||||||
from flask.ext.appbuilder.models.mixins import AuditMixin
|
from flask.ext.appbuilder.models.mixins import AuditMixin
|
||||||
from pydruid.client import PyDruid
|
|
||||||
from flask.ext.appbuilder.models.decorators import renders
|
from flask.ext.appbuilder.models.decorators import renders
|
||||||
|
from flask.ext.babelpkg import lazy_gettext as _
|
||||||
|
|
||||||
|
from pydruid.client import PyDruid
|
||||||
from pydruid.utils.filters import Dimension, Filter
|
from pydruid.utils.filters import Dimension, Filter
|
||||||
from pydruid.utils.postaggregator import Postaggregator
|
from pydruid.utils.postaggregator import Postaggregator
|
||||||
from six import string_types
|
from six import string_types
|
||||||
|
@ -33,7 +36,6 @@ from sqlalchemy.engine import reflection
|
||||||
from sqlalchemy.ext.declarative import declared_attr
|
from sqlalchemy.ext.declarative import declared_attr
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
from sqlalchemy.sql import table, literal_column, text, column
|
from sqlalchemy.sql import table, literal_column, text, column
|
||||||
from sqlalchemy.sql.elements import ColumnClause
|
|
||||||
from sqlalchemy_utils import EncryptedType
|
from sqlalchemy_utils import EncryptedType
|
||||||
|
|
||||||
from caravel import app, db, get_session, utils
|
from caravel import app, db, get_session, utils
|
||||||
|
@ -571,9 +573,9 @@ class SqlaTable(Model, Queryable, AuditMixinNullable):
|
||||||
qry_start_dttm = datetime.now()
|
qry_start_dttm = datetime.now()
|
||||||
|
|
||||||
if not granularity and is_timeseries:
|
if not granularity and is_timeseries:
|
||||||
raise Exception(
|
raise Exception(_(
|
||||||
"Datetime column not provided as part table configuration "
|
"Datetime column not provided as part table configuration "
|
||||||
"and is required by this type of chart")
|
"and is required by this type of chart"))
|
||||||
|
|
||||||
metrics_exprs = [
|
metrics_exprs = [
|
||||||
m.sqla_col
|
m.sqla_col
|
||||||
|
@ -1191,7 +1193,7 @@ class DruidDatasource(Model, AuditMixinNullable, Queryable):
|
||||||
query_str += json.dumps(client.query_dict, indent=2)
|
query_str += json.dumps(client.query_dict, indent=2)
|
||||||
df = client.export_pandas()
|
df = client.export_pandas()
|
||||||
if df is None or df.size == 0:
|
if df is None or df.size == 0:
|
||||||
raise Exception("No data was returned.")
|
raise Exception(_("No data was returned."))
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not is_timeseries and
|
not is_timeseries and
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
|
|
||||||
{% macro locale_menu(languages) %}
|
|
||||||
{% set locale = session['locale'] %}
|
{% set locale = session['locale'] %}
|
||||||
{% if not locale %}
|
{% if not locale %}
|
||||||
{% set locale = 'en' %}
|
{% set locale = 'en' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if languages.keys()|length > 1 %}
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">
|
<a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">
|
||||||
<div class="f16"><i class="flag {{languages[locale].get('flag')}}"></i><b class="caret"></b>
|
<div class="f16"><i class="flag {{languages[locale].get('flag')}}"></i><b class="caret"></b>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{% if languages.keys()|length > 1 %}
|
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
{% for lang in languages %}
|
{% for lang in languages %}
|
||||||
|
@ -21,9 +20,8 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
|
||||||
</li>
|
</li>
|
||||||
{% endmacro %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
{% block head_css %}
|
{% block head_css %}
|
||||||
<link rel="stylesheet" type="text/css" href="/static/assets/node_modules/font-awesome/css/font-awesome.min.css" />
|
<link rel="stylesheet" type="text/css" href="/static/assets/node_modules/font-awesome/css/font-awesome.min.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="/static/assets/stylesheets/caravel.css" />
|
<link rel="stylesheet" type="text/css" href="/static/assets/stylesheets/caravel.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="/static/appbuilder/css/flags/flags16.css" />
|
||||||
<link rel="icon" type="image/png" href="/static/assets/images/favicon.png">
|
<link rel="icon" type="image/png" href="/static/assets/images/favicon.png">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block head_js %}
|
{% block head_js %}
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
<script src="/static/assets/javascripts/dist/welcome.entry.js"></script>
|
<script src="/static/assets/javascripts/dist/welcome.entry.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block title %}Welcome!{% endblock %}
|
{% block title %}{{ _("Welcome!") }}{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container welcome">
|
<div class="container welcome">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h3>Welcome!</h3>
|
<h3>{{ _("Welcome!") }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div id="cal-heatmap"></div>
|
<div id="cal-heatmap"></div>
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
# Spanish translations for PROJECT.
|
||||||
|
# Copyright (C) 2016 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the PROJECT project.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2016-05-02 00:21-0700\n"
|
||||||
|
"PO-Revision-Date: 2016-05-02 08:49-0700\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language: es\n"
|
||||||
|
"Language-Team: es <LL@li.org>\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: Babel 2.3.4\n"
|
||||||
|
|
||||||
|
#: caravel/models.py:564
|
||||||
|
msgid ""
|
||||||
|
"Datetime column not provided as part table configuration and is required "
|
||||||
|
"by this type of chart"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/models.py:1153
|
||||||
|
msgid "No data was returned."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:116
|
||||||
|
msgid ""
|
||||||
|
"Whether to make this column available as a [Time Granularity] option, "
|
||||||
|
"column has to be DATETIME or DATETIME-like"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:215
|
||||||
|
msgid "Databases"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:217 caravel/views.py:261 caravel/views.py:284
|
||||||
|
msgid "Sources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:260
|
||||||
|
msgid "Tables"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:282
|
||||||
|
msgid "Druid Clusters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:313
|
||||||
|
msgid "Slices"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:341
|
||||||
|
msgid ""
|
||||||
|
"This json object describes the positioning of the widgets in the "
|
||||||
|
"dashboard. It is dynamically generated when adjusting the widgets size "
|
||||||
|
"and positions by using drag & drop in the dashboard view"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:346
|
||||||
|
msgid ""
|
||||||
|
"The css for individual dashboards can be altered here, or in the "
|
||||||
|
"dashboard view where changes are immediately visible"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:367
|
||||||
|
msgid "Dashboards"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:392
|
||||||
|
msgid "Action Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:393
|
||||||
|
msgid "Security"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:430
|
||||||
|
msgid "Druid Datasources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:514
|
||||||
|
msgid "The datasource seems to have been deleted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:522
|
||||||
|
msgid "You don't seem to have access to this datasource"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:843
|
||||||
|
msgid "This view requires the `all_datasource_access` permission"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:954
|
||||||
|
msgid "CSS Templates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:34
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:35
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:40
|
||||||
|
msgid "Login"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/caravel/welcome.html:8
|
||||||
|
#: caravel/templates/caravel/welcome.html:13
|
||||||
|
msgid "Welcome!"
|
||||||
|
msgstr ""
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,118 @@
|
||||||
|
# French translations for PROJECT.
|
||||||
|
# Copyright (C) 2016 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the PROJECT project.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2016-05-02 00:21-0700\n"
|
||||||
|
"PO-Revision-Date: 2016-05-01 23:07-0700\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"Language-Team: fr <LL@li.org>\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: Babel 2.3.4\n"
|
||||||
|
|
||||||
|
#: caravel/models.py:564
|
||||||
|
msgid ""
|
||||||
|
"Datetime column not provided as part table configuration and is required "
|
||||||
|
"by this type of chart"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/models.py:1153
|
||||||
|
msgid "No data was returned."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:116
|
||||||
|
msgid ""
|
||||||
|
"Whether to make this column available as a [Time Granularity] option, "
|
||||||
|
"column has to be DATETIME or DATETIME-like"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:215
|
||||||
|
msgid "Databases"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:217 caravel/views.py:261 caravel/views.py:284
|
||||||
|
msgid "Sources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:260
|
||||||
|
msgid "Tables"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:282
|
||||||
|
msgid "Druid Clusters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:313
|
||||||
|
msgid "Slices"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:341
|
||||||
|
msgid ""
|
||||||
|
"This json object describes the positioning of the widgets in the "
|
||||||
|
"dashboard. It is dynamically generated when adjusting the widgets size "
|
||||||
|
"and positions by using drag & drop in the dashboard view"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:346
|
||||||
|
msgid ""
|
||||||
|
"The css for individual dashboards can be altered here, or in the "
|
||||||
|
"dashboard view where changes are immediately visible"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:367
|
||||||
|
msgid "Dashboards"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:392
|
||||||
|
msgid "Action Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:393
|
||||||
|
msgid "Security"
|
||||||
|
msgstr "Securité"
|
||||||
|
|
||||||
|
#: caravel/views.py:430
|
||||||
|
msgid "Druid Datasources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:514
|
||||||
|
msgid "The datasource seems to have been deleted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:522
|
||||||
|
msgid "You don't seem to have access to this datasource"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:843
|
||||||
|
msgid "This view requires the `all_datasource_access` permission"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:954
|
||||||
|
msgid "CSS Templates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:34
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:35
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:40
|
||||||
|
msgid "Login"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/caravel/welcome.html:8
|
||||||
|
#: caravel/templates/caravel/welcome.html:13
|
||||||
|
msgid "Welcome!"
|
||||||
|
msgstr "Bienvenue!"
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,118 @@
|
||||||
|
# Chinese translations for PROJECT.
|
||||||
|
# Copyright (C) 2016 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the PROJECT project.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2016-05-02 00:21-0700\n"
|
||||||
|
"PO-Revision-Date: 2016-05-01 23:07-0700\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language: zh\n"
|
||||||
|
"Language-Team: zh <LL@li.org>\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: Babel 2.3.4\n"
|
||||||
|
|
||||||
|
#: caravel/models.py:564
|
||||||
|
msgid ""
|
||||||
|
"Datetime column not provided as part table configuration and is required "
|
||||||
|
"by this type of chart"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/models.py:1153
|
||||||
|
msgid "No data was returned."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:116
|
||||||
|
msgid ""
|
||||||
|
"Whether to make this column available as a [Time Granularity] option, "
|
||||||
|
"column has to be DATETIME or DATETIME-like"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:215
|
||||||
|
msgid "Databases"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:217 caravel/views.py:261 caravel/views.py:284
|
||||||
|
msgid "Sources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:260
|
||||||
|
msgid "Tables"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:282
|
||||||
|
msgid "Druid Clusters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:313
|
||||||
|
msgid "Slices"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:341
|
||||||
|
msgid ""
|
||||||
|
"This json object describes the positioning of the widgets in the "
|
||||||
|
"dashboard. It is dynamically generated when adjusting the widgets size "
|
||||||
|
"and positions by using drag & drop in the dashboard view"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:346
|
||||||
|
msgid ""
|
||||||
|
"The css for individual dashboards can be altered here, or in the "
|
||||||
|
"dashboard view where changes are immediately visible"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:367
|
||||||
|
msgid "Dashboards"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:392
|
||||||
|
msgid "Action Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:393
|
||||||
|
msgid "Security"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:430
|
||||||
|
msgid "Druid Datasources"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:514
|
||||||
|
msgid "The datasource seems to have been deleted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:522
|
||||||
|
msgid "You don't seem to have access to this datasource"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:843
|
||||||
|
msgid "This view requires the `all_datasource_access` permission"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/views.py:954
|
||||||
|
msgid "CSS Templates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:34
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:35
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/appbuilder/navbar_right.html:40
|
||||||
|
msgid "Login"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: caravel/templates/caravel/welcome.html:8
|
||||||
|
#: caravel/templates/caravel/welcome.html:13
|
||||||
|
msgid "Welcome!"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -13,13 +13,16 @@ from datetime import datetime
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import sqlalchemy as sqla
|
import sqlalchemy as sqla
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
g, request, redirect, flash, Response, render_template, Markup)
|
g, request, redirect, flash, Response, render_template, Markup)
|
||||||
from flask.ext.appbuilder import ModelView, CompactCRUDMixin, BaseView, expose
|
from flask.ext.appbuilder import ModelView, CompactCRUDMixin, BaseView, expose
|
||||||
from flask.ext.appbuilder.actions import action
|
from flask.ext.appbuilder.actions import action
|
||||||
from flask.ext.appbuilder.models.sqla.interface import SQLAInterface
|
from flask.ext.appbuilder.models.sqla.interface import SQLAInterface
|
||||||
from flask.ext.appbuilder.security.decorators import has_access
|
from flask.ext.appbuilder.security.decorators import has_access
|
||||||
|
from flask.ext.babelpkg import lazy_gettext as _
|
||||||
from flask_appbuilder.models.sqla.filters import BaseFilter
|
from flask_appbuilder.models.sqla.filters import BaseFilter
|
||||||
|
|
||||||
from pydruid.client import doublesum
|
from pydruid.client import doublesum
|
||||||
from sqlalchemy import create_engine, select, text
|
from sqlalchemy import create_engine, select, text
|
||||||
from sqlalchemy.sql.expression import TextAsFrom
|
from sqlalchemy.sql.expression import TextAsFrom
|
||||||
|
@ -110,10 +113,10 @@ class TableColumnInlineView(CompactCRUDMixin, CaravelModelView): # noqa
|
||||||
'sum', 'min', 'max', 'is_dttm']
|
'sum', 'min', 'max', 'is_dttm']
|
||||||
page_size = 500
|
page_size = 500
|
||||||
description_columns = {
|
description_columns = {
|
||||||
'is_dttm': (
|
'is_dttm': (_(
|
||||||
"Whether to make this column available as a "
|
"Whether to make this column available as a "
|
||||||
"[Time Granularity] option, column has to be DATETIME or "
|
"[Time Granularity] option, column has to be DATETIME or "
|
||||||
"DATETIME-like"),
|
"DATETIME-like")),
|
||||||
'expression': utils.markdown(
|
'expression': utils.markdown(
|
||||||
"a valid SQL expression as supported by the underlying backend. "
|
"a valid SQL expression as supported by the underlying backend. "
|
||||||
"Example: `substr(name, 1, 1)`", True),
|
"Example: `substr(name, 1, 1)`", True),
|
||||||
|
@ -215,8 +218,9 @@ class DatabaseView(CaravelModelView, DeleteMixin): # noqa
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
DatabaseView,
|
DatabaseView,
|
||||||
"Databases",
|
"Databases",
|
||||||
|
label=_("Databases"),
|
||||||
icon="fa-database",
|
icon="fa-database",
|
||||||
category="Sources",
|
category=_("Sources"),
|
||||||
category_icon='fa-database',)
|
category_icon='fa-database',)
|
||||||
|
|
||||||
|
|
||||||
|
@ -259,8 +263,8 @@ class TableModelView(CaravelModelView, DeleteMixin): # noqa
|
||||||
|
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
TableModelView,
|
TableModelView,
|
||||||
"Tables",
|
_("Tables"),
|
||||||
category="Sources",
|
category=_("Sources"),
|
||||||
icon='fa-table',)
|
icon='fa-table',)
|
||||||
|
|
||||||
|
|
||||||
|
@ -281,9 +285,9 @@ class DruidClusterModelView(CaravelModelView, DeleteMixin): # noqa
|
||||||
if config['DRUID_IS_ACTIVE']:
|
if config['DRUID_IS_ACTIVE']:
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
DruidClusterModelView,
|
DruidClusterModelView,
|
||||||
"Druid Clusters",
|
_("Druid Clusters"),
|
||||||
icon="fa-cubes",
|
icon="fa-cubes",
|
||||||
category="Sources",
|
category=_("Sources"),
|
||||||
category_icon='fa-database',)
|
category_icon='fa-database',)
|
||||||
|
|
||||||
|
|
||||||
|
@ -312,7 +316,7 @@ class SliceModelView(CaravelModelView, DeleteMixin): # noqa
|
||||||
|
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
SliceModelView,
|
SliceModelView,
|
||||||
"Slices",
|
_("Slices"),
|
||||||
icon="fa-bar-chart",
|
icon="fa-bar-chart",
|
||||||
category="",
|
category="",
|
||||||
category_icon='',)
|
category_icon='',)
|
||||||
|
@ -340,12 +344,12 @@ class DashboardModelView(CaravelModelView, DeleteMixin): # noqa
|
||||||
add_columns = edit_columns
|
add_columns = edit_columns
|
||||||
base_order = ('changed_on', 'desc')
|
base_order = ('changed_on', 'desc')
|
||||||
description_columns = {
|
description_columns = {
|
||||||
'position_json': (
|
'position_json': _(
|
||||||
"This json object describes the positioning of the widgets in "
|
"This json object describes the positioning of the widgets in "
|
||||||
"the dashboard. It is dynamically generated when adjusting "
|
"the dashboard. It is dynamically generated when adjusting "
|
||||||
"the widgets size and positions by using drag & drop in "
|
"the widgets size and positions by using drag & drop in "
|
||||||
"the dashboard view"),
|
"the dashboard view"),
|
||||||
'css': (
|
'css': _(
|
||||||
"The css for individual dashboards can be altered here, or "
|
"The css for individual dashboards can be altered here, or "
|
||||||
"in the dashboard view where changes are immediately "
|
"in the dashboard view where changes are immediately "
|
||||||
"visible"),
|
"visible"),
|
||||||
|
@ -366,7 +370,9 @@ class DashboardModelView(CaravelModelView, DeleteMixin): # noqa
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
DashboardModelView,
|
DashboardModelView,
|
||||||
"Dashboards",
|
"Dashboards",
|
||||||
|
label=_("Dashboards"),
|
||||||
icon="fa-dashboard",
|
icon="fa-dashboard",
|
||||||
|
|
||||||
category="",
|
category="",
|
||||||
category_icon='',)
|
category_icon='',)
|
||||||
|
|
||||||
|
@ -389,7 +395,8 @@ class LogModelView(CaravelModelView):
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
LogModelView,
|
LogModelView,
|
||||||
"Action Log",
|
"Action Log",
|
||||||
category="Security",
|
label=_("Action Log"),
|
||||||
|
category=_("Security"),
|
||||||
icon="fa-list-ol")
|
icon="fa-list-ol")
|
||||||
|
|
||||||
|
|
||||||
|
@ -423,6 +430,7 @@ if config['DRUID_IS_ACTIVE']:
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
DruidDatasourceModelView,
|
DruidDatasourceModelView,
|
||||||
"Druid Datasources",
|
"Druid Datasources",
|
||||||
|
label=_("Druid Datasources"),
|
||||||
category="Sources",
|
category="Sources",
|
||||||
icon="fa-cube")
|
icon="fa-cube")
|
||||||
|
|
||||||
|
@ -506,7 +514,7 @@ class Caravel(BaseView):
|
||||||
.first()
|
.first()
|
||||||
)
|
)
|
||||||
if not datasource:
|
if not datasource:
|
||||||
flash("The datasource seems to have been deleted", "alert")
|
flash(_("The datasource seems to have been deleted"), "alert")
|
||||||
return redirect(error_redirect)
|
return redirect(error_redirect)
|
||||||
|
|
||||||
all_datasource_access = self.appbuilder.sm.has_access(
|
all_datasource_access = self.appbuilder.sm.has_access(
|
||||||
|
@ -514,7 +522,7 @@ class Caravel(BaseView):
|
||||||
datasource_access = self.appbuilder.sm.has_access(
|
datasource_access = self.appbuilder.sm.has_access(
|
||||||
'datasource_access', datasource.perm)
|
'datasource_access', datasource.perm)
|
||||||
if not (all_datasource_access or datasource_access):
|
if not (all_datasource_access or datasource_access):
|
||||||
flash("You don't seem to have access to this datasource", "danger")
|
flash(_("You don't seem to have access to this datasource"), "danger")
|
||||||
return redirect(error_redirect)
|
return redirect(error_redirect)
|
||||||
|
|
||||||
action = request.args.get('action')
|
action = request.args.get('action')
|
||||||
|
@ -835,8 +843,8 @@ class Caravel(BaseView):
|
||||||
if (
|
if (
|
||||||
not self.appbuilder.sm.has_access(
|
not self.appbuilder.sm.has_access(
|
||||||
'all_datasource_access', 'all_datasource_access')):
|
'all_datasource_access', 'all_datasource_access')):
|
||||||
raise Exception(
|
raise Exception(_(
|
||||||
"This view requires the `all_datasource_access` permission")
|
"This view requires the `all_datasource_access` permission"))
|
||||||
content = ""
|
content = ""
|
||||||
if mydb:
|
if mydb:
|
||||||
eng = mydb.get_sqla_engine()
|
eng = mydb.get_sqla_engine()
|
||||||
|
@ -946,6 +954,7 @@ appbuilder.add_separator("Sources")
|
||||||
appbuilder.add_view(
|
appbuilder.add_view(
|
||||||
CssTemplateModelView,
|
CssTemplateModelView,
|
||||||
"CSS Templates",
|
"CSS Templates",
|
||||||
|
label=_("CSS Templates"),
|
||||||
icon="fa-css3",
|
icon="fa-css3",
|
||||||
category="Sources",
|
category="Sources",
|
||||||
category_icon='')
|
category_icon='')
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
cd caravel/assets/
|
||||||
|
npm run prod
|
||||||
|
cd ../..
|
||||||
|
python setup.py register
|
||||||
|
python setup.py sdist upload
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -16,8 +16,10 @@ setup(
|
||||||
scripts=['caravel/bin/caravel'],
|
scripts=['caravel/bin/caravel'],
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'alembic>=0.8.5, <0.9.0',
|
'alembic>=0.8.5, <0.9.0',
|
||||||
|
'babel==2.3.4',
|
||||||
'cryptography>=1.1.1, <2.0.0',
|
'cryptography>=1.1.1, <2.0.0',
|
||||||
'flask-appbuilder>=1.6.0, <2.0.0',
|
'flask-appbuilder>=1.6.0, <2.0.0',
|
||||||
|
'Flask-BabelPkg==0.9.6',
|
||||||
'flask-cache>=0.13.1, <0.14.0',
|
'flask-cache>=0.13.1, <0.14.0',
|
||||||
'flask-migrate>=1.5.1, <2.0.0',
|
'flask-migrate>=1.5.1, <2.0.0',
|
||||||
'flask-script>=2.0.5, <3.0.0',
|
'flask-script>=2.0.5, <3.0.0',
|
||||||
|
|
Loading…
Reference in New Issue