Babel locale
This commit is contained in:
parent
08e68e35b8
commit
426d1fe531
3
babel.cfg
Normal file
3
babel.cfg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[python: **.py]
|
||||||
|
[jinja2: **/templates/**.html]
|
||||||
|
extensions=jinja2.ext.autoescape,jinja2.ext.with_
|
|
@ -1,8 +0,0 @@
|
||||||
from flask import render_template
|
|
||||||
from objects import glob
|
|
||||||
|
|
||||||
@glob.app.context_processor
|
|
||||||
def locale():
|
|
||||||
def _locale(lang, key):
|
|
||||||
return glob.langs[lang][key] if key in glob.langs[lang] else key
|
|
||||||
return dict(locale = _locale)
|
|
|
@ -6,14 +6,14 @@ from flask_login import UserMixin
|
||||||
from objects import glob
|
from objects import glob
|
||||||
|
|
||||||
class BillForm(Form):
|
class BillForm(Form):
|
||||||
payment_to = StringField("lbl_to", [validators.DataRequired()])
|
payment_to = StringField("Payment to", [validators.DataRequired()])
|
||||||
description = TextAreaField("lbl_desc", render_kw = {
|
description = TextAreaField("Description", render_kw = {
|
||||||
"cols": 55,
|
"cols": 55,
|
||||||
"rows": 8
|
"rows": 8
|
||||||
})
|
})
|
||||||
sum = DecimalField("lbl_sum")
|
sum = DecimalField("Sum")
|
||||||
kid = IntegerField("lbl_id")
|
kid = IntegerField("KID")
|
||||||
date_due = DateField("lbl_date")
|
date_due = DateField("Date due")
|
||||||
|
|
||||||
class LoginForm(Form):
|
class LoginForm(Form):
|
||||||
email = StringField("Email", [
|
email = StringField("Email", [
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"lbl_to": "Payment to",
|
|
||||||
"lbl_desc": "Description",
|
|
||||||
"lbl_sum": "Sum",
|
|
||||||
"lbl_id": "KID",
|
|
||||||
"lbl_date": "Date due",
|
|
||||||
"lbl_status": "Payment status"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"add": "Add",
|
|
||||||
"close": "Close"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"lnk_dashboard": "Dashboard",
|
|
||||||
"lnk_bills": "Bills",
|
|
||||||
"lnk_receipts": "Receipts",
|
|
||||||
"lnk_warranties": "Warranties",
|
|
||||||
"ttl_economical": "Economical"
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"lbl_to": "Betaling til",
|
|
||||||
"lbl_desc": "Tekst",
|
|
||||||
"lbl_sum": "Sum",
|
|
||||||
"lbl_id": "KID",
|
|
||||||
"lbl_date": "Forfallsdato",
|
|
||||||
"lbl_status": "Betalingsstatus"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"add": "Legg til",
|
|
||||||
"close": "Lukk"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"lnk_dashboard": "Dashbord",
|
|
||||||
"lnk_bills": "Regninger",
|
|
||||||
"lnk_receipts": "Kvitteringer",
|
|
||||||
"lnk_warranties": "Garantier",
|
|
||||||
"ttl_economical": "Økonomisk"
|
|
||||||
}
|
|
17
localizer.py
Normal file
17
localizer.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from flask import g, request, session
|
||||||
|
from flask_babel import Babel
|
||||||
|
|
||||||
|
from objects import glob
|
||||||
|
|
||||||
|
babel = Babel(glob.app)
|
||||||
|
|
||||||
|
LANGUAGES = {
|
||||||
|
"en": "English",
|
||||||
|
"no": "Norwegian"
|
||||||
|
}
|
||||||
|
|
||||||
|
@babel.localeselector
|
||||||
|
def get_locale():
|
||||||
|
if request.args.get("lang"):
|
||||||
|
session["lang"] = request.args.get("lang") if request.args.get("lang") in LANGUAGES.keys() else "en"
|
||||||
|
return session.get("lang", "en")
|
3
main.py
3
main.py
|
@ -5,8 +5,9 @@ from objects import glob # Global sharing of python objects in a manageable way
|
||||||
glob.app = Flask(__name__)
|
glob.app = Flask(__name__)
|
||||||
glob.app.secret_key = "E2FGrJXLtOxPh70Q"
|
glob.app.secret_key = "E2FGrJXLtOxPh70Q"
|
||||||
|
|
||||||
|
import localizer # Initialize localization (Babel)
|
||||||
import routes # All flask app routes
|
import routes # All flask app routes
|
||||||
import filters # All flask app filters
|
# import filters # All flask app filters
|
||||||
|
|
||||||
if glob.config["git"]["auto_pull_and_restart"]: # Only used on the VPS (Do not enable in config)
|
if glob.config["git"]["auto_pull_and_restart"]: # Only used on the VPS (Do not enable in config)
|
||||||
@glob.app.route(glob.config["git"]["webhook_endpoint"], methods = ["POST"])
|
@glob.app.route(glob.config["git"]["webhook_endpoint"], methods = ["POST"])
|
||||||
|
|
|
@ -10,8 +10,6 @@ import bcrypt
|
||||||
app = None # main.py -> Flask App
|
app = None # main.py -> Flask App
|
||||||
sql_conn = None
|
sql_conn = None
|
||||||
|
|
||||||
langs = {}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Global variables that initializes on first load of module
|
# Global variables that initializes on first load of module
|
||||||
|
|
||||||
|
@ -22,19 +20,6 @@ if not os.path.isfile("config.json"):
|
||||||
with open("config.json", "r") as f:
|
with open("config.json", "r") as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
|
||||||
path = "locale"
|
|
||||||
for l in os.listdir(path):
|
|
||||||
langs[l] = {}
|
|
||||||
_path = "%s/%s" % (path, l)
|
|
||||||
for f in os.listdir(_path):
|
|
||||||
_f = "%s/%s" % (_path, f)
|
|
||||||
with open(_f, "r", encoding = "UTF-8") as j:
|
|
||||||
pnd = json.load(j)
|
|
||||||
for k in pnd.keys():
|
|
||||||
if k in langs[l]:
|
|
||||||
raise Exception("Duplicate localization entries found in file %s" % _f)
|
|
||||||
langs[l] = {**langs[l], **pnd}
|
|
||||||
|
|
||||||
def make_sql_connection():
|
def make_sql_connection():
|
||||||
return mysql.connector.connect(**config["mysql"])
|
return mysql.connector.connect(**config["mysql"])
|
||||||
|
|
||||||
|
|
19
routes.py
19
routes.py
|
@ -6,6 +6,8 @@ from forms.login import LoginForm, RegisterForm, BillForm, User, register_accoun
|
||||||
|
|
||||||
from objects import glob # Global sharing of python objects in a manageable way
|
from objects import glob # Global sharing of python objects in a manageable way
|
||||||
|
|
||||||
|
from flask_babel import gettext
|
||||||
|
|
||||||
login_manager = flask_login.LoginManager()
|
login_manager = flask_login.LoginManager()
|
||||||
login_manager.init_app(glob.app)
|
login_manager.init_app(glob.app)
|
||||||
login_manager.login_view = "login"
|
login_manager.login_view = "login"
|
||||||
|
@ -65,7 +67,7 @@ def receipts():
|
||||||
@glob.app.route("/login", methods = ["GET", "POST"])
|
@glob.app.route("/login", methods = ["GET", "POST"])
|
||||||
def login():
|
def login():
|
||||||
if flask_login.current_user.is_authenticated:
|
if flask_login.current_user.is_authenticated:
|
||||||
flash("Already logged in", "info")
|
flash(gettext("Already logged in"), "info")
|
||||||
return redirect(url_for("dashboard"))
|
return redirect(url_for("dashboard"))
|
||||||
|
|
||||||
form = LoginForm(request.form)
|
form = LoginForm(request.form)
|
||||||
|
@ -73,20 +75,20 @@ def login():
|
||||||
try:
|
try:
|
||||||
user = User((form.email.data, form.password.data))
|
user = User((form.email.data, form.password.data))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
flash(str(e), "danger")
|
flash(gettext(str(e)), "danger")
|
||||||
return render_template("login.html", form=form)
|
return render_template("login.html", form=form)
|
||||||
|
|
||||||
flask_login.login_user(user)
|
flask_login.login_user(user)
|
||||||
logged_in_users.append(user)
|
logged_in_users.append(user)
|
||||||
|
|
||||||
flash("Logged in", "success")
|
flash(gettext("Logged in"), "success")
|
||||||
return redirect(url_for("dashboard"))
|
return redirect(url_for("dashboard"))
|
||||||
return render_template("login.html", form=form)
|
return render_template("login.html", form=form)
|
||||||
|
|
||||||
@glob.app.route("/register", methods = ["GET", "POST"])
|
@glob.app.route("/register", methods = ["GET", "POST"])
|
||||||
def register():
|
def register():
|
||||||
if flask_login.current_user.is_authenticated:
|
if flask_login.current_user.is_authenticated:
|
||||||
flash("Already logged in", "info")
|
flash(gettext("Already logged in"), "info")
|
||||||
return redirect(url_for("dashboard"))
|
return redirect(url_for("dashboard"))
|
||||||
|
|
||||||
form = RegisterForm(request.form)
|
form = RegisterForm(request.form)
|
||||||
|
@ -94,10 +96,10 @@ def register():
|
||||||
try:
|
try:
|
||||||
register_account(form.email.data, form.password.data, form.firstname.data, form.surname.data)
|
register_account(form.email.data, form.password.data, form.firstname.data, form.surname.data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
flash(str(e), "danger")
|
flash(gettext(str(e)), "danger")
|
||||||
return render_template("register.html", form=form)
|
return render_template("register.html", form=form)
|
||||||
|
|
||||||
flash("User registered", "success")
|
flash(gettext("User registered"), "success")
|
||||||
return redirect(url_for("login"))
|
return redirect(url_for("login"))
|
||||||
return render_template("register.html", form=form)
|
return render_template("register.html", form=form)
|
||||||
|
|
||||||
|
@ -105,12 +107,12 @@ def register():
|
||||||
@flask_login.login_required
|
@flask_login.login_required
|
||||||
def logout():
|
def logout():
|
||||||
flask_login.logout_user()
|
flask_login.logout_user()
|
||||||
flash("Logged out", "success")
|
flash(gettext("Logged out"), "success")
|
||||||
return redirect(url_for("login"))
|
return redirect(url_for("login"))
|
||||||
|
|
||||||
@glob.app.errorhandler(401)
|
@glob.app.errorhandler(401)
|
||||||
def unauthorized_handler_err():
|
def unauthorized_handler_err():
|
||||||
flash("Login is required", "danger")
|
flash(gettext("Login is required"), "danger")
|
||||||
unauthorized_handler()
|
unauthorized_handler()
|
||||||
|
|
||||||
@login_manager.user_loader
|
@login_manager.user_loader
|
||||||
|
@ -122,4 +124,3 @@ def load_user(uuid):
|
||||||
@login_manager.unauthorized_handler
|
@login_manager.unauthorized_handler
|
||||||
def unauthorized_handler():
|
def unauthorized_handler():
|
||||||
return redirect(url_for("login"))
|
return redirect(url_for("login"))
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
{% set LANG = "no" %} <!-- TODO: Dynamic lang swap -->
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
{% include 'layout/includes/boot-head.html' %}
|
{% include 'layout/includes/boot-head.html' %}
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/custom.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/custom.css') }}">
|
||||||
{% if title %}
|
{% if title %}
|
||||||
<title>Husstanden - {{ locale(LANG, title) }}</title>
|
<title>Husstanden - {{ _(title) | title }}</title>
|
||||||
{% else %}
|
{% else %}
|
||||||
<title>Husstanden</title>
|
<title>Husstanden</title>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -105,29 +105,29 @@
|
||||||
<div class="flex-column">
|
<div class="flex-column">
|
||||||
<div> <!-- Collection -->
|
<div> <!-- Collection -->
|
||||||
<a class="item" href="{{ url_for('dashboard') }}">
|
<a class="item" href="{{ url_for('dashboard') }}">
|
||||||
<i class="far fa-calendar-alt"></i><span>{{ locale(LANG, "lnk_dashboard") }}</span>
|
<i class="far fa-calendar-alt"></i><span>{{ _("Dashboard") }}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4>{{ locale(LANG, "ttl_economical") }}</h4>
|
<h4>{{ _("Economical") }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a class="item" href="{{ url_for('bills') }}">
|
<a class="item" href="{{ url_for('bills') }}">
|
||||||
<i class="fas fa-money-check-alt"></i><span>{{ locale(LANG, "lnk_bills") }}</span>
|
<i class="fas fa-money-check-alt"></i><span>{{ _("Bills") }}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a class="item" onclick="toggleCategory(this)">
|
<a class="item" onclick="toggleCategory(this)">
|
||||||
<i class="far fa-list-alt"></i><span>{{ locale(LANG, "lnk_receipts") }}</span>
|
<i class="far fa-list-alt"></i><span>{{ _("Receipts") }}</span>
|
||||||
<i class="fas fa-chevron-right"></i>
|
<i class="fas fa-chevron-right"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="downtab hidden">
|
<div class="downtab hidden">
|
||||||
<div class="flex-column">
|
<div class="flex-column">
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<a href="{{ url_for('receipts') }}">{{ locale(LANG, "lnk_receipts") }}</a>
|
<a href="{{ url_for('receipts') }}">{{ _("Receipts") }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<a href="{{ url_for('warranties') }}">{{ locale(LANG, "lnk_warranties") }}</a>
|
<a href="{{ url_for('warranties') }}">{{ _("Warranties") }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<style>
|
<style>
|
||||||
.rndblock {
|
.rndblock {
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background: #506EE4;
|
background: #506EE4;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
@ -15,11 +15,24 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.languk {
|
.lang-icon {
|
||||||
|
background-position: left;
|
||||||
|
background-size: contain;
|
||||||
|
width: 32px;
|
||||||
|
height: 24px;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-en {
|
||||||
background-image: url("{{ url_for('static', filename='const/img/flags/gb.svg') }}");
|
background-image: url("{{ url_for('static', filename='const/img/flags/gb.svg') }}");
|
||||||
}
|
}
|
||||||
|
|
||||||
.langno {
|
.lang-no {
|
||||||
background-image: url("{{ url_for('static', filename='const/img/flags/no.svg') }}");
|
background-image: url("{{ url_for('static', filename='const/img/flags/no.svg') }}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +47,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<nav class="navbar topnav" style="margin-bottom: 10px;">
|
<nav class="navbar topnav" style="margin-bottom: 10px;">
|
||||||
<h3>{{ locale(LANG, title) }}</h3>
|
<h3>{{ _(title) | title }}</h3>
|
||||||
<div>
|
<div>
|
||||||
{% with messages = get_flashed_messages(with_categories = true) %}
|
{% with messages = get_flashed_messages(with_categories = true) %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
|
@ -49,7 +62,25 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="my-2 my-lg-0 d-flex icon-buttons">
|
<div class="my-2 my-lg-0 d-flex icon-buttons">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="rndblock languk"></div>
|
<div class="rndblock lang-{{ session.lang }}" data-toggle="dropdown" aria-expanded="false"></div>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<div class="row">
|
||||||
|
<a class="col d-flex m-1" href="?lang=en">
|
||||||
|
<div class="lang-icon lang-en"></div>
|
||||||
|
<div class="flex-grow-1"></div>
|
||||||
|
<span>{{ _("english") | title }}</span>
|
||||||
|
<div class="flex-grow-1"></div>
|
||||||
|
</a>
|
||||||
|
<a class="col d-flex m-1" href="?lang=no">
|
||||||
|
<div class="lang-icon lang-no"></div>
|
||||||
|
<div class="flex-grow-1"></div>
|
||||||
|
<span>{{ _("norwegian") | title }}</span>
|
||||||
|
<div class="flex-grow-1"></div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="rndblock">
|
<div class="rndblock">
|
||||||
|
@ -64,7 +95,7 @@
|
||||||
<li>
|
<li>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a href="{{ url_for('logout') }}">Sign out</a>
|
<a href="{{ url_for('logout') }}">{{ _("Sign out") }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% set title = "lnk_bills" %}
|
{% set title = "Bills" %}
|
||||||
|
|
||||||
{% extends "layout/dash.html" %}
|
{% extends "layout/dash.html" %}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<div class="container module">
|
<div class="container module">
|
||||||
|
|
||||||
<button type="button" class="btn btn-primary" style="margin:10px;" data-toggle="modal" data-target="#myModal">{{ locale(LANG, "add") }}</button>
|
<button type="button" class="btn btn-primary" style="margin:10px;" data-toggle="modal" data-target="#myModal">{{ _("Add") }}</button>
|
||||||
<div class="modal fade" id="myModal" role="dialog">
|
<div class="modal fade" id="myModal" role="dialog">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<!-- Modal content-->
|
<!-- Modal content-->
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
{% macro render_field(field) %}
|
{% macro render_field(field) %}
|
||||||
<dt><label for="{{ field.label.field_id }}">{{ locale(LANG, field.label.text) }}</label>
|
<dt><label for="{{ field.label.field_id }}">{{ _(field.label.text) }}</label>
|
||||||
<dd>{{ field(**kwargs)|safe }}
|
<dd>{{ field(**kwargs)|safe }}
|
||||||
{% if field.errors %}
|
{% if field.errors %}
|
||||||
<ul class=errors>
|
<ul class=errors>
|
||||||
|
@ -42,11 +42,11 @@
|
||||||
{{ render_field(form.kid) }}
|
{{ render_field(form.kid) }}
|
||||||
{{ render_field(form.date_due) }}
|
{{ render_field(form.date_due) }}
|
||||||
</dl>
|
</dl>
|
||||||
<input type=submit value="{{ locale(LANG, 'add') }}">
|
<input type=submit value="{{ _('Add') }}">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ locale(LANG, "close") }}</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ _("Close") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,12 +55,12 @@
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead class="thead-light">
|
<thead class="thead-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{{ locale(LANG, "lbl_to") }}</th>
|
<th scope="col">{{ _("Payment to") }}</th>
|
||||||
<th scope="col">{{ locale(LANG, "lbl_desc") }}</th>
|
<th scope="col">{{ _("Description") }}</th>
|
||||||
<th scope="col" style="width: 120px">{{ locale(LANG, "lbl_sum") }}</th>
|
<th scope="col" style="width: 120px">{{ _("Sum") }}</th>
|
||||||
<th scope="col" style="width: 220px">{{ locale(LANG, "lbl_id") }}</th>
|
<th scope="col" style="width: 220px">{{ _("KID") }}</th>
|
||||||
<th scope="col" style="width: 120px">{{ locale(LANG, "lbl_date") }}</th>
|
<th scope="col" style="width: 120px">{{ _("Date due") }}</th>
|
||||||
<th scope="col" style="width: 150px">{{ locale(LANG, "lbl_status") }}</th>
|
<th scope="col" style="width: 150px">{{ _("Payment status") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% set title = "lnk_dashboard" %}
|
{% set title = "Dashboard" %}
|
||||||
|
|
||||||
{% extends "layout/dash.html" %}
|
{% extends "layout/dash.html" %}
|
||||||
|
|
||||||
|
|
102
translations/nb/LC_MESSAGES/messages.po
Normal file
102
translations/nb/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
# Norwegian text and messages
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: 0.4\n"
|
||||||
|
"Report-Msgid-Bugs-To: noreply@osufx.com\n"
|
||||||
|
"POT-Creation-Date: 2019-05-12 15:57+0200\n"
|
||||||
|
"PO-Revision-Date: 2015-05-12 09:47+1000\n"
|
||||||
|
"Last-Translator: Emily Steinsvik <emily@osufx.com>\n"
|
||||||
|
"Language: no\n"
|
||||||
|
"Language-Team: no <emily@osufx.com>\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.6.0\n"
|
||||||
|
|
||||||
|
#: routes.py:70 routes.py:91
|
||||||
|
msgid "Already logged in"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: routes.py:84
|
||||||
|
msgid "Logged in"
|
||||||
|
msgstr "Logget inn"
|
||||||
|
|
||||||
|
#: routes.py:102
|
||||||
|
msgid "User registered"
|
||||||
|
msgstr "Bruker registrert"
|
||||||
|
|
||||||
|
#: routes.py:110
|
||||||
|
msgid "Logged out"
|
||||||
|
msgstr "Logget ut"
|
||||||
|
|
||||||
|
#: routes.py:115
|
||||||
|
msgid "Login is required"
|
||||||
|
msgstr "Innlogging kreves"
|
||||||
|
|
||||||
|
#: templates/layout/includes/side_nav.html:108
|
||||||
|
msgid "Dashboard"
|
||||||
|
msgstr "Dashbord"
|
||||||
|
|
||||||
|
#: templates/layout/includes/side_nav.html:112
|
||||||
|
msgid "Economical"
|
||||||
|
msgstr "Økonomisk"
|
||||||
|
|
||||||
|
#: templates/layout/includes/side_nav.html:116
|
||||||
|
msgid "Bills"
|
||||||
|
msgstr "Regninger"
|
||||||
|
|
||||||
|
#: templates/layout/includes/side_nav.html:121
|
||||||
|
#: templates/layout/includes/side_nav.html:127
|
||||||
|
msgid "Receipts"
|
||||||
|
msgstr "Kvitteringer"
|
||||||
|
|
||||||
|
#: templates/layout/includes/side_nav.html:130
|
||||||
|
msgid "Warranties"
|
||||||
|
msgstr "Garantier"
|
||||||
|
|
||||||
|
#: templates/layout/includes/top_nav.html:72
|
||||||
|
msgid "english"
|
||||||
|
msgstr "engelsk"
|
||||||
|
|
||||||
|
#: templates/layout/includes/top_nav.html:78
|
||||||
|
msgid "norwegian"
|
||||||
|
msgstr "norsk"
|
||||||
|
|
||||||
|
#: templates/layout/includes/top_nav.html:98
|
||||||
|
msgid "Sign out"
|
||||||
|
msgstr "Logg ut"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:15 templates/pages/bills.html:45
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "Legg til"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:49
|
||||||
|
msgid "Close"
|
||||||
|
msgstr "Lukk"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:58
|
||||||
|
msgid "Payment to"
|
||||||
|
msgstr "Betaling til"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:59
|
||||||
|
msgid "Description"
|
||||||
|
msgstr "Tekst"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:60
|
||||||
|
msgid "Sum"
|
||||||
|
msgstr "Sum"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:61
|
||||||
|
msgid "KID"
|
||||||
|
msgstr "KID"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:62
|
||||||
|
msgid "Date due"
|
||||||
|
msgstr "Forfallsdato"
|
||||||
|
|
||||||
|
#: templates/pages/bills.html:63
|
||||||
|
msgid "Payment status"
|
||||||
|
msgstr "Betalingsstatus"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user