1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

Merge branch 'monthly-payment' into staging

This commit is contained in:
Sylvain 2021-02-02 17:18:36 +01:00
commit b4dc4fca83
205 changed files with 5631 additions and 16619 deletions

View File

@ -4,6 +4,8 @@
- Refactored theme builder to use scss files
- Updated stripe gem to 5.21.0
- Architecture documentation
- Improved coupon creation/deletion workflow
- Default texts for the login modal
- Fix a bug: unable to access embedded plan views
- Fix a bug: warning message overflow in credit wallet modal
- Fix a bug: when using a cash coupon, the amount shown in the statistics is invalid
@ -16,6 +18,18 @@
- [TODO DEPLOY] add the `INTL_CURRENCY` environment variable (see [doc/environment.md](doc/environment.md#INTL_CURRENCY) for configuration details)
- [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/mount-payment-schedules.sh | bash`
## v4.6.6 2021 February 02
- Full German translation (thanks to [@korrupt](https://crowdin.com/profile/korrupt))
- OpenAPI endpoints to create/update/show/delete machines
- Updated environment documentation
- Removed useless locales' configuration files
- OpenAPI's endpoints will now return more detailed error messages when something wrong occurs
- Fix a bug: when an event is modified, the member's reservations does not reflect the new event date
- Fix a security issue: updated ini to 1.3.8 to fix [CVE-2020-7788](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7788)
- Fix a security issue: updated nokogiri to 1.11.1 to fix [CVE-2020-26247](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26247)
- Updated caxlsx to 3.0.4, and the dependencies of caxlsx_rail
- [TODO DEPLOY] -> (only dev) `bundle install`
## v4.6.5 2020 December 07
- Fix a bug: unable to run the upgrade script with docker-compose >= v1.19
@ -36,7 +50,7 @@
- Removed fab-manager email address from the seeds
- Initialize new plans with default prices for machines & spaces
- Display a message when no plans are available
- Fix a bug: in the settings area, boolean switches are always shown as false
- Fix a bug: in the settings' area, boolean switches are always shown as false
- Fix a bug: public cards presenting the plans in the public area, have bogus style
- Fix a bug: theme primary color is ignored on links
- [TODO DEPLOY] `rails fablab:maintenance:rebuild_stylesheet`
@ -45,7 +59,7 @@
- Add intermediate step version for upgrades: v4.4.6. This will prevent issues with FootprintDebug if a regeneration is needed
- Check postgreSQL status before compiling assets
- Improved documentation about the upgrade process
- Improved the documentation about the upgrade process
- Fix a bug: unable to set libraries locales to their default values (en-us)
- Fix a bug: unable to display details about a closed period
- Fix a bug: members cannot view available trainings slots
@ -53,7 +67,7 @@
## v4.6.1 2020 October 21
- Reduced down time during upgrades
- Reduced downtime during upgrades
- Architecture changes to allow including React.js components into the application
- Allow running upgrade scripts from dev ranch
- Fix a bug: script mount-webpack.sh was not updating the docker-compose.yml file

View File

@ -75,7 +75,7 @@ GEM
image_processing (~> 1.1)
mimemagic (>= 0.3.0)
mini_mime (>= 0.1.3)
caxlsx (3.0.1)
caxlsx (3.0.4)
htmlentities (~> 4.3, >= 4.3.4)
mimemagic (~> 0.3)
nokogiri (~> 1.10, >= 1.10.4)
@ -87,7 +87,7 @@ GEM
cldr-plurals-runtime-rb (1.0.1)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
concurrent-ruby (1.1.7)
concurrent-ruby (1.1.8)
connection_pool (2.2.3)
coveralls_reborn (0.18.0)
simplecov (>= 0.18.1, < 0.20.0)
@ -132,7 +132,7 @@ GEM
faraday
multi_json
equalizer (0.0.11)
erubi (1.9.0)
erubi (1.10.0)
et-orbi (1.2.1)
tzinfo
faker (2.10.2)
@ -156,7 +156,7 @@ GEM
httparty (0.18.0)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
i18n (1.8.5)
i18n (1.8.7)
concurrent-ruby (~> 1.0)
icalendar (2.5.3)
ice_cube (~> 0.16)
@ -187,7 +187,7 @@ GEM
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
loofah (2.7.0)
loofah (2.9.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@ -203,8 +203,8 @@ GEM
mimemagic (0.3.5)
mini_magick (4.10.1)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.14.2)
mini_portile2 (2.5.0)
minitest (5.14.3)
minitest-reporters (1.4.2)
ansi
builder
@ -215,8 +215,9 @@ GEM
multi_xml (0.6.0)
multipart-post (2.1.1)
nio4r (2.5.4)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
nokogiri (1.11.1)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
notify_with (0.0.2)
jbuilder (~> 2.0)
rails (>= 4.2.0)
@ -265,6 +266,7 @@ GEM
pundit (2.1.0)
activesupport (>= 3.0.0)
raabro (1.1.6)
racc (1.5.2)
rack (2.2.3)
rack-protection (2.0.8.1)
rack
@ -334,7 +336,7 @@ GEM
rubyXL (3.4.14)
nokogiri (>= 1.10.8)
rubyzip (>= 1.3.0)
rubyzip (1.3.0)
rubyzip (2.3.0)
safe_yaml (1.0.5)
sassc (2.2.1)
ffi (~> 1.9)
@ -386,7 +388,7 @@ GEM
camertron-eprun
cldr-plurals-runtime-rb (~> 1.0)
tzinfo
tzinfo (1.2.7)
tzinfo (1.2.9)
thread_safe (~> 0.1)
tzinfo-data (1.2020.4)
tzinfo (>= 1.0.0)

View File

@ -1,4 +1,4 @@
#web: bundle exec rails server puma -p $PORT
web: bundle exec rails server puma -p $PORT
worker: bundle exec sidekiq -C ./config/sidekiq.yml
wp-client: bin/webpack-dev-server
wp-server: SERVER_BUNDLE_ONLY=yes bin/webpack --watch

View File

@ -23,7 +23,6 @@ class API::InvoicesController < API::ApiController
p = params.require(:query).permit(:number, :customer, :date, :order_by, :page, :size)
render json: { error: 'page must be an integer' }, status: :unprocessable_entity and return unless p[:page].is_a? Integer
render json: { error: 'size must be an integer' }, status: :unprocessable_entity and return unless p[:size].is_a? Integer
order = InvoicesService.parse_order(p[:order_by])

View File

@ -5,6 +5,21 @@ class API::PaymentSchedulesController < API::ApiController
before_action :authenticate_user!
before_action :set_payment_schedule, only: %i[download]
def list
authorize PaymentSchedule
p = params.require(:query).permit(:reference, :customer, :date, :page, :size)
render json: { error: 'page must be an integer' }, status: :unprocessable_entity and return unless p[:page].is_a? Integer
render json: { error: 'size must be an integer' }, status: :unprocessable_entity and return unless p[:size].is_a? Integer
@payment_schedules = PaymentScheduleService.list(
p[:page],
p[:size],
reference: p[:reference], customer: p[:customer], date: p[:date]
)
end
def download
authorize @payment_schedule
send_file File.join(Rails.root, @payment_schedule.file), type: 'application/pdf', disposition: 'attachment'

View File

@ -97,6 +97,7 @@ class API::PaymentsController < API::ApiController
def on_reservation_success(intent, details)
@reservation = Reservation.new(reservation_params)
payment_method = params[:cart_items][:reservation][:payment_method] || 'stripe'
user_id = if current_user.admin? || current_user.manager?
params[:cart_items][:reservation][:user_id]
else
@ -107,7 +108,7 @@ class API::PaymentsController < API::ApiController
payment_details: details,
intent_id: intent.id,
schedule: params[:cart_items][:reservation][:payment_schedule],
payment_method: params[:cart_items][:reservation][:payment_method])
payment_method: payment_method)
if intent.class == Stripe::PaymentIntent
Stripe::PaymentIntent.update(
intent.id,

View File

@ -1,5 +1,9 @@
# frozen_string_literal: true
# Parameters for OpenAPI endpoints
class OpenAPI::V1::BaseController < ActionController::Base
protect_from_forgery with: :null_session
skip_before_action :verify_authenticity_token
before_action :authenticate
before_action :increment_calls_count
@ -7,15 +11,24 @@ class OpenAPI::V1::BaseController < ActionController::Base
rescue_from OpenAPI::ParameterError, with: :bad_request
rescue_from ActionController::ParameterMissing, with: :bad_request
rescue_from TypeError, with: :server_error
rescue_from NoMethodError, with: :server_error
rescue_from ArgumentError, with: :server_error
helper_method :current_api_client
protected
def not_found
render json: { errors: ["Not found"] }, status: :not_found
def not_found(exception)
render json: { errors: ['Not found', exception] }, status: :not_found
end
def bad_request
render json: { errors: ["Bad request"] }, status: :bad_request
def bad_request(exception)
render json: { errors: ['Bad request', exception] }, status: :bad_request
end
def server_error(exception)
render json: { error: ['Server error', exception] }, status: :internal_server_error
end
def authenticate
@ -23,7 +36,7 @@ class OpenAPI::V1::BaseController < ActionController::Base
end
def authenticate_token
authenticate_with_http_token do |token, options|
authenticate_with_http_token do |token, _options|
@open_api_client = OpenAPI::Client.find_by(token: token)
end
end
@ -37,6 +50,7 @@ class OpenAPI::V1::BaseController < ActionController::Base
end
private
def increment_calls_count
@open_api_client.increment_calls_count
end

View File

@ -1,3 +1,4 @@
# OpenAPI controller for the invoices
class OpenAPI::V1::InvoicesController < OpenAPI::V1::BaseController
extend OpenAPI::ApiDoc
expose_doc
@ -5,15 +6,13 @@ class OpenAPI::V1::InvoicesController < OpenAPI::V1::BaseController
def index
@invoices = Invoice.order(created_at: :desc)
if params[:user_id].present?
@invoices = @invoices.where(user_id: params[:user_id])
end
@invoices = @invoices.where(user_id: params[:user_id]) if params[:user_id].present?
return unless params[:page].present?
if params[:page].present?
@invoices = @invoices.page(params[:page]).per(per_page)
paginate @invoices, per_page: per_page
end
end
def download
@invoice = Invoice.find(params[:id])

View File

@ -1,8 +1,52 @@
# frozen_string_literal: true
# authorized 3rd party softwares can manage the machines through the OpenAPI
class OpenAPI::V1::MachinesController < OpenAPI::V1::BaseController
extend OpenAPI::ApiDoc
expose_doc
before_action :set_machine, only: %i[show update destroy]
def index
@machines = Machine.order(:created_at)
end
def create
@machine = Machine.new(machine_params)
if @machine.save
render :show, status: :created, location: @machine
else
render json: @machine.errors, status: :unprocessable_entity
end
end
def update
if @machine.update(machine_params)
render :show, status: :ok, location: @machine
else
render json: @machine.errors, status: :unprocessable_entity
end
end
def show; end
def destroy
if @machine.destroyable?
@machine.destroy
head :no_content
else
render json: { error: 'has existing reservations' }, status: :unprocessable_entity
end
end
private
def machine_params
params.require(:machine).permit(:name, :description, :spec, :disabled,
machine_image_attributes: [:attachment])
end
def set_machine
@machine = Machine.friendly.find(params[:id])
end
end

View File

@ -83,4 +83,100 @@ class OpenAPI::V1::MachinesDoc < OpenAPI::V1::BaseDoc
}
MACHINES
end
doc_for :create do
api :POST, "/#{API_VERSION}/machines", 'Create a machine'
formats %w[json multipart/form-data]
description 'Create a new machine.'
returns code: 201, desc: 'The machine was successfully created'
param :machine, Hash, required: true do
param :name, String, desc: 'The name of the machine.', required: true
param :description, String, desc: 'A long textual description of the machine. HTML is supported.', required: true
param :spec, String, desc: 'A long textual description of the technical specifications of the machine. HTML is supported.'
param :disabled, [TrueClass, FalseClass], desc: "Should the machine be disabled? If yes, the machine won't be reservable and will be shown apart."
param :machine_image_attributes, Hash do
param :attachment, ActionDispatch::Http::UploadedFile, required: true, desc: 'Upload a picture for the machine.'
end
end
example <<-MACHINE
curl -X POST
-H "Authorization:Token token=xxx"
-H "Content-Type:multipart/form-data"
-H "Accept: application/json"
-F machine[name]="Epilog laser"
-F machine[description]="La découpeuse laser vous permet de découper ou graver des matériaux."
-F machine[machine_image_attributes[attachment]]=@epilog.jpeg
/open_api/v1/machines
curl -X POST
-H "Authorization:Token token=xxx"
-H "Content-Type:application/json"
-H "Accept: application/json"
-d '{"machine": { "name": "DMP Flex 100", "description": "Cette imprimante 3D peut imprimer des métaux." }}'
/open_api/v1/machines
MACHINE
end
doc_for :update do
api :PATCH, "/#{API_VERSION}/machines/:id", 'Update a machine'
formats %w[json multipart/form-data]
description 'Update an existing machine.'
returns code: 200, desc: 'The machine was successfully updated'
param :machine, Hash, required: true do
param :name, String, desc: 'The name of the machine.', required: true
param :description, String, desc: 'A long textual description of the machine. HTML is supported.', required: true
param :spec, String, desc: 'A long textual description of the technical specifications of the machine. HTML is supported.'
param :disabled, [TrueClass, FalseClass], desc: "Should the machine be disabled? If yes, the machine won't be reservable and will be shown apart."
param :machine_image_attributes, Hash do
param :attachment, ActionDispatch::Http::UploadedFile, required: true, desc: 'Upload a picture for the machine.'
end
end
example <<-MACHINE
curl -X PATCH
-H "Authorization:Token token=xxx"
-H "Content-Type:multipart/form-data"
-H "Accept: application/json"
-F machine[spec]="Laser CO2 de 60W<br>Surface de travail de 812 x 508 mm"
-F machine[machine_image_attributes[attachment]]=@epilog2.jpg
/open_api/v1/machines/10
curl -X PATCH
-H "Authorization:Token token=xxx"
-H "Content-Type:application/json"
-H "Accept: application/json"
-d '{"machine": { "disabled": true }}'
/open_api/v1/machines/10
MACHINE
end
doc_for :show do
api :GET, "/#{API_VERSION}/machines/:id", 'Show a machine'
description 'Show all the details of single machine.'
example <<-MACHINES
# /open_api/v1/machines/1
{
"id": 1,
"name": "Epilog EXT36 Laser",
"slug": "decoupeuse-laser",
"disabled": false,
"updated_at": "2015-02-17T11:06:00.495+01:00",
"created_at": "2014-06-30T03:32:31.972+02:00",
"description": "La découpeuse Laser, EPILOG Legend 36EXT\r\n\r\nInformations générales :\r\nLa découpeuse laser vous permet de découper ou graver des matériaux. \r\n\r\nPour la découpe, il suffit d'apporter votre fichier vectorisé type illustrator, svg ou dxf avec des \"lignes de coupe\" d'une épaisseur inférieure à 0,01 mm et la machine s'occupera du reste!\r\n\r\nLa gravure est basée sur le spectre noir et blanc. Les nuances sont obtenues par différentes profondeurs de gravure correspondant aux niveaux de gris de votre image. Il suffit pour cela d'apporter une image scannée ou un fichier photo en noir et blanc pour pouvoir reproduire celle-ci sur votre support.\r\n\r\nTypes de matériaux gravables/découpeables ?\r\nDu bois au tissu, du plexiglass au cuir, cette machine permet de découper et graver la plupart des matériaux sauf les métaux. La gravure est néanmoins possible sur les métaux recouverts d'une couche de peinture ou les aluminiums anodisés. \r\nConcernant l'épaisseur des matériaux découpés, il est préférable de ne pas dépasser 5 mm pour le bois et 6 mm pour le plexiglass.\r\n",
"spec": "Puissance : 40W\r\nSurface de travail : 914x609 mm \r\nEpaisseur maximale de la matière : 305mm\r\nSource laser : tube laser type CO2\r\nContrôles de vitesse et de puissance : ces deux paramètres sont ajustables en fonction du matériau (de 1% à 100%) .\r\n",
"image": "/uploads/machine_image/2514/machine_image.jpg"
}
MACHINES
end
doc_for :destroy do
api :DELETE, "/#{API_VERSION}/machines/:id", 'Delete a machine'
description 'Delete an existing machine that does not have any existing reservations.'
returns code: 204, desc: 'The machine was successfully deleted'
example <<-MACHINE
curl -X DELETE
-H "Authorization:Token token=xxx"
-H "Accept: application/json"
/open_api/v1/machines/10
MACHINE
end
end

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
# Raised when trying to create something based on a subscription but it does not exists or is expired
class InvalidSubscriptionError < StandardError
end

View File

@ -0,0 +1,17 @@
import apiClient from './api-client';
import { AxiosResponse } from 'axios';
import { PaymentSchedule, PaymentScheduleIndexRequest } from '../models/payment-schedule';
import wrapPromise, { IWrapPromise } from '../lib/wrap-promise';
export default class PaymentScheduleAPI {
async list (query: PaymentScheduleIndexRequest): Promise<Array<PaymentSchedule>> {
const res: AxiosResponse = await apiClient.post(`/api/payment_schedules/list`, query);
return res?.data;
}
static list (query: PaymentScheduleIndexRequest): IWrapPromise<Array<PaymentSchedule>> {
const api = new PaymentScheduleAPI();
return wrapPromise(api.list(query));
}
}

View File

@ -0,0 +1,57 @@
/**
* This component shows 3 input fields for filtering invoices/payment-schedules by reference, customer name and date
*/
import React, { useEffect, useState } from 'react';
import { LabelledInput } from './labelled-input';
import { useTranslation } from 'react-i18next';
interface DocumentFiltersProps {
onFilterChange: (value: { reference: string, customer: string, date: Date }) => void
}
export const DocumentFilters: React.FC<DocumentFiltersProps> = ({ onFilterChange }) => {
const { t } = useTranslation('admin');
const [referenceFilter, setReferenceFilter] = useState('');
const [customerFilter, setCustomerFilter] = useState('');
const [dateFilter, setDateFilter] = useState(null);
useEffect(() => {
onFilterChange({ reference: referenceFilter, customer: customerFilter, date: dateFilter });
}, [referenceFilter, customerFilter, dateFilter])
const handleReferenceUpdate = (e) => {
setReferenceFilter(e.target.value);
}
const handleCustomerUpdate = (e) => {
setCustomerFilter(e.target.value);
}
const handleDateUpdate = (e) => {
let date = e.target.value;
if (e.target.value === '') date = null;
setDateFilter(date);
}
return (
<div className="document-filters">
<LabelledInput id="reference"
label={t('app.admin.invoices.document_filters.reference')}
type="text"
onChange={handleReferenceUpdate}
value={referenceFilter} />
<LabelledInput id="customer"
label={t('app.admin.invoices.document_filters.customer')}
type="text"
onChange={handleCustomerUpdate}
value={customerFilter} />
<LabelledInput id="reference"
label={t('app.admin.invoices.document_filters.date')}
type="date"
onChange={handleDateUpdate}
value={dateFilter ? dateFilter : ''} />
</div>
);
}

View File

@ -0,0 +1,22 @@
/**
* This component shows input field with its label, styled
*/
import React from 'react';
interface LabelledInputProps {
id: string,
type: string,
label: string,
value: any,
onChange: (value: any) => void
}
export const LabelledInput: React.FC<LabelledInputProps> = ({ id, type, label, value, onChange }) => {
return (
<div className="input-with-label">
<label className="label" htmlFor={id}>{label}</label>
<input className="input" id={id} type={type} value={value} onChange={onChange} />
</div>
);
}

View File

@ -0,0 +1,53 @@
/**
* This component shows a list of all payment schedules with their associated deadlines (aka. PaymentScheduleItem) and invoices
*/
import React, { useState } from 'react';
import { IApplication } from '../models/application';
import { useTranslation } from 'react-i18next';
import { Loader } from './loader';
import { react2angular } from 'react2angular';
import PaymentScheduleAPI from '../api/payment-schedule';
import { DocumentFilters } from './document-filters';
import { PaymentSchedulesTable } from './payment-schedules-table';
declare var Application: IApplication;
const paymentSchedulesList = PaymentScheduleAPI.list({ query: { page: 1, size: 20 } });
const PaymentSchedulesList: React.FC = () => {
const { t } = useTranslation('admin');
const [paymentSchedules, setPaymentSchedules] = useState(paymentSchedulesList.read());
const handleFiltersChange = ({ reference, customer, date }): void => {
const api = new PaymentScheduleAPI();
api.list({ query: { reference, customer, date, page: 1, size: 20 }}).then((res) => {
setPaymentSchedules(res);
});
};
return (
<div className="payment-schedules-list">
<h3>
<i className="fas fa-filter" />
{t('app.admin.invoices.payment_schedules.filter_schedules')}
</h3>
<div className="schedules-filters">
<DocumentFilters onFilterChange={handleFiltersChange} />
</div>
<PaymentSchedulesTable paymentSchedules={paymentSchedules} showCustomer={true} />
</div>
);
}
const PaymentSchedulesListWrapper: React.FC = () => {
return (
<Loader>
<PaymentSchedulesList />
</Loader>
);
}
Application.Components.component('paymentSchedulesList', react2angular(PaymentSchedulesListWrapper));

View File

@ -0,0 +1,253 @@
/**
* This component shows a list of all payment schedules with their associated deadlines (aka. PaymentScheduleItem) and invoices
*/
import React, { ReactEventHandler, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Loader } from './loader';
import moment from 'moment';
import { IFablab } from '../models/fablab';
import _ from 'lodash';
import { PaymentSchedule, PaymentScheduleItem, PaymentScheduleItemState } from '../models/payment-schedule';
declare var Fablab: IFablab;
interface PaymentSchedulesTableProps {
paymentSchedules: Array<PaymentSchedule>,
showCustomer?: boolean
}
const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({ paymentSchedules, showCustomer }) => {
const { t } = useTranslation('admin');
const [showExpanded, setShowExpanded] = useState({});
/**
* Check if the requested payment schedule is displayed with its deadlines (PaymentScheduleItem) or without them
*/
const isExpanded = (paymentScheduleId: number): boolean => {
return showExpanded[paymentScheduleId];
}
/**
* Return the formatted localized date for the given date
*/
const formatDate = (date: Date): string => {
return Intl.DateTimeFormat().format(moment(date).toDate());
}
/**
* Return the formatted localized amount for the given price (eg. 20.5 => "20,50 €")
*/
const formatPrice = (price: number): string => {
return new Intl.NumberFormat(Fablab.intl_locale, {style: 'currency', currency: Fablab.intl_currency}).format(price);
}
/**
* Return the value for the CSS property 'display', for the payment schedule deadlines
*/
const statusDisplay = (paymentScheduleId: number): string => {
if (isExpanded(paymentScheduleId)) {
return 'table-row'
} else {
return 'none';
}
}
/**
* Return the action icon for showing/hiding the deadlines
*/
const expandCollapseIcon = (paymentScheduleId: number): JSX.Element => {
if (isExpanded(paymentScheduleId)) {
return <i className="fas fa-minus-square" />;
} else {
return <i className="fas fa-plus-square" />
}
}
/**
* Show or hide the deadlines for the provided payment schedule, inverting their current status
*/
const togglePaymentScheduleDetails = (paymentScheduleId: number): ReactEventHandler => {
return (): void => {
if (isExpanded(paymentScheduleId)) {
setShowExpanded(Object.assign({}, showExpanded, { [paymentScheduleId]: false }));
} else {
setShowExpanded(Object.assign({}, showExpanded, { [paymentScheduleId]: true }));
}
}
}
/**
* For use with downloadButton()
*/
enum TargetType {
Invoice = 'invoices',
PaymentSchedule = 'payment_schedules'
}
/**
* Return a button to download a PDF file, may be an invoice, or a payment schedule, depending or the provided parameters
*/
const downloadButton = (target: TargetType, id: number): JSX.Element => {
const link = `api/${target}/${id}/download`;
return (
<a href={link} target="_blank" className="download-button">
<i className="fas fa-download" />
{t('app.admin.invoices.schedules_table.download')}
</a>
);
}
/**
* Return the human-readable string for the status of the provided deadline.
*/
const formatState = (item: PaymentScheduleItem): JSX.Element => {
let res = t(`app.admin.invoices.schedules_table.state_${item.state}`);
if (item.state === PaymentScheduleItemState.Paid) {
const key = `app.admin.invoices.schedules_table.method_${item.payment_method}`
res += ` (${t(key)})`;
}
return <span className={`state-${item.state}`}>{res}</span>;
}
/**
* Return the action button(s) for the given deadline
*/
const itemButtons = (item: PaymentScheduleItem): JSX.Element => {
switch (item.state) {
case PaymentScheduleItemState.Paid:
return downloadButton(TargetType.Invoice, item.invoice_id);
case PaymentScheduleItemState.Pending:
return (
<button className="action-button" onClick={handleConfirmCheckPayment(item)}>
<i className="fas fa-money-check" />
{t('app.admin.invoices.schedules_table.confirm_payment')}
</button>
);
case PaymentScheduleItemState.RequireAction:
return (
<button className="action-button" onClick={handleSolveAction(item)}>
<i className="fas fa-wrench" />
{t('app.admin.invoices.schedules_table.solve')}
</button>
);
case PaymentScheduleItemState.RequirePaymentMethod:
return (
<button className="action-button" onClick={handleUpdateCard(item)}>
<i className="fas fa-credit-card" />
{t('app.admin.invoices.schedules_table.update_card')}
</button>
);
default:
return <span />
}
}
const handleConfirmCheckPayment = (item: PaymentScheduleItem): ReactEventHandler => {
return (): void => {
/*
TODO
- display confirmation modal
- create /api/payment_schedule/item/confirm_check endpoint and post to it
*/
}
}
const handleSolveAction = (item: PaymentScheduleItem): ReactEventHandler => {
return (): void => {
/*
TODO
- create component wrapped with <StripeElements>
- stripe.confirmCardSetup(item.client_secret).then(function(result) {
if (result.error) {
// Display error.message in your UI.
} else {
// The setup has succeeded. Display a success message.
}
});
*/
}
}
const handleUpdateCard = (item: PaymentScheduleItem): ReactEventHandler => {
return (): void => {
/*
TODO
- Notify the customer, collect new payment information, and create a new payment method
- Attach the payment method to the customer
- Update the default payment method
- Pay the invoice using the new payment method
*/
}
}
return (
<div>
<table className="schedules-table">
<thead>
<tr>
<th className="w-35" />
<th className="w-200">{t('app.admin.invoices.schedules_table.schedule_num')}</th>
<th className="w-200">{t('app.admin.invoices.schedules_table.date')}</th>
<th className="w-120">{t('app.admin.invoices.schedules_table.price')}</th>
{showCustomer && <th className="w-200">{t('app.admin.invoices.schedules_table.customer')}</th>}
<th className="w-200"/>
</tr>
</thead>
<tbody>
{paymentSchedules.map(p => <tr key={p.id}>
<td colSpan={6}>
<table className="schedules-table-body">
<tbody>
<tr>
<td className="w-35 row-header" onClick={togglePaymentScheduleDetails(p.id)}>{expandCollapseIcon(p.id)}</td>
<td className="w-200">{p.reference}</td>
<td className="w-200">{formatDate(p.created_at)}</td>
<td className="w-120">{formatPrice(p.total)}</td>
{showCustomer && <td className="w-200">{p.user.name}</td>}
<td className="w-200">{downloadButton(TargetType.PaymentSchedule, p.id)}</td>
</tr>
<tr style={{ display: statusDisplay(p.id) }}>
<td className="w-35" />
<td colSpan={5}>
<div>
<table className="schedule-items-table">
<thead>
<tr>
<th className="w-120">{t('app.admin.invoices.schedules_table.deadline')}</th>
<th className="w-120">{t('app.admin.invoices.schedules_table.amount')}</th>
<th className="w-200">{t('app.admin.invoices.schedules_table.state')}</th>
<th className="w-200" />
</tr>
</thead>
<tbody>
{_.orderBy(p.items, 'due_date').map(item => <tr key={item.id}>
<td>{formatDate(item.due_date)}</td>
<td>{formatPrice(item.amount)}</td>
<td>{formatState(item)}</td>
<td>{itemButtons(item)}</td>
</tr>)}
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>)}
</tbody>
</table>
</div>
);
};
PaymentSchedulesTableComponent.defaultProps = { showCustomer: false };
export const PaymentSchedulesTable: React.FC<PaymentSchedulesTableProps> = ({ paymentSchedules, showCustomer }) => {
return (
<Loader>
<PaymentSchedulesTableComponent paymentSchedules={paymentSchedules} showCustomer={showCustomer} />
</Loader>
);
}

View File

@ -7,7 +7,6 @@ import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from "@stripe/stripe-js";
import SettingAPI from '../api/setting';
import { SettingName } from '../models/setting';
import { Loader } from './loader';
const stripePublicKey = SettingAPI.get(SettingName.StripePublicKey);

View File

@ -174,7 +174,7 @@ const StripeModal: React.FC<StripeModalProps> = ({ isOpen, toggleModal, afterSuc
customFooter={logoFooter()}
className="stripe-modal">
{ready && <StripeElements>
<WalletInfo reservation={cartItems?.reservation} currentUser={currentUser} wallet={wallet} price={price?.price} />
<WalletInfo cartItems={cartItems} currentUser={currentUser} wallet={wallet} price={price?.price} />
<StripeForm onSubmit={handleSubmit}
onSuccess={handleFormSuccess}
onError={handleFormError}

View File

@ -8,23 +8,25 @@ import { react2angular } from 'react2angular';
import { IApplication } from '../models/application';
import '../lib/i18n';
import { Loader } from './loader';
import { Reservation } from '../models/reservation';
import { User } from '../models/user';
import { Wallet } from '../models/wallet';
import { IFablab } from '../models/fablab';
import WalletLib from '../lib/wallet';
import { CartItems } from '../models/payment';
import { Reservation } from '../models/reservation';
import { SubscriptionRequest } from '../models/subscription';
declare var Application: IApplication;
declare var Fablab: IFablab;
interface WalletInfoProps {
reservation: Reservation,
cartItems: CartItems,
currentUser: User,
wallet: Wallet,
price: number,
}
export const WalletInfo: React.FC<WalletInfoProps> = ({reservation, currentUser, wallet, price}) => {
export const WalletInfo: React.FC<WalletInfoProps> = ({ cartItems, currentUser, wallet, price }) => {
const { t } = useTranslation('shared');
const [remainingPrice, setRemainingPrice] = useState(0);
@ -34,20 +36,26 @@ export const WalletInfo: React.FC<WalletInfoProps> = ({reservation, currentUser,
useEffect(() => {
const wLib = new WalletLib(wallet);
setRemainingPrice(wLib.computeRemainingPrice(price));
})
});
/**
* Return the formatted localized amount for the given price (eg. 20.5 => "20,50 €")
* Return the formatted localized amount for the given price (e.g. 20.5 => "20,50 €")
*/
const formatPrice = (price: number): string => {
return new Intl.NumberFormat(Fablab.intl_locale, {style: 'currency', currency: Fablab.intl_currency}).format(price);
}
/**
* Check if the currently connected used is also the person making the reservation.
* If the currently connected user (ie. the operator), is an admin or a manager, he may book the reservation for someone else.
* If the currently connected user (i.e. the operator), is an admin or a manager, he may book the reservation for someone else.
*/
const isOperatorAndClient = (): boolean => {
return currentUser.id == reservation.user_id;
return currentUser.id == buyingItem().user_id;
}
/**
* Return the item currently bought (reservation or subscription)
*/
const buyingItem = (): Reservation|SubscriptionRequest => {
return cartItems.reservation || cartItems.subscription;
}
/**
* If the client has some money in his wallet & the price is not zero, then we should display this component.
@ -66,17 +74,17 @@ export const WalletInfo: React.FC<WalletInfoProps> = ({reservation, currentUser,
* Does the current cart contains a payment schedule?
*/
const isPaymentSchedule = (): boolean => {
return reservation.plan_id && reservation.payment_schedule;
return buyingItem().plan_id && buyingItem().payment_schedule;
}
/**
* Return the human-readable name of the item currently bought with the wallet
*/
const getPriceItem = (): string => {
let item = 'other';
if (reservation.slots_attributes.length > 0) {
if (cartItems.reservation) {
item = 'reservation';
} else if (reservation.plan_id) {
if (reservation.payment_schedule) {
} else if (cartItems.subscription) {
if (cartItems.subscription.payment_schedule) {
item = 'first_deadline';
} else item = 'subscription';
}
@ -120,12 +128,12 @@ export const WalletInfo: React.FC<WalletInfoProps> = ({reservation, currentUser,
);
}
const WalletInfoWrapper: React.FC<WalletInfoProps> = ({currentUser, reservation, price, wallet}) => {
const WalletInfoWrapper: React.FC<WalletInfoProps> = ({ currentUser, cartItems, price, wallet }) => {
return (
<Loader>
<WalletInfo currentUser={currentUser} reservation={reservation} price={price} wallet={wallet}/>
<WalletInfo currentUser={currentUser} cartItems={cartItems} price={price} wallet={wallet}/>
</Loader>
);
}
Application.Components.component('walletInfo', react2angular(WalletInfoWrapper, ['currentUser', 'price', 'reservation', 'wallet']));
Application.Components.component('walletInfo', react2angular(WalletInfoWrapper, ['currentUser', 'price', 'cartItems', 'wallet']));

View File

@ -704,9 +704,12 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'growl', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems', 'stripeKey',
function ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, growl, wallet, helpers, $filter, coupon, cartItems, stripeKey) {
// User's wallet amount
$scope.walletAmount = wallet.amount;
$scope.wallet = wallet;
// Price
$scope.price = price.price;
// Amount to pay
$scope.amount = helpers.getAmountToPay(price.price, wallet.amount);
// Cart items
@ -753,16 +756,22 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
},
coupon () {
return $scope.coupon.applied;
}
},
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', 'coupon',
function ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation, wallet, helpers, $filter, coupon) {
cartItems () {
return mkRequestParams(reservation, $scope.coupon.applied);
},
},
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems',
function ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation, wallet, helpers, $filter, coupon, cartItems) {
// User's wallet amount
$scope.walletAmount = wallet.amount;
$scope.wallet = wallet;
// Price
$scope.price = price.price;
// Cart items
$scope.cartItems = cartItems;
// price to pay
$scope.amount = helpers.getAmountToPay(price.price, wallet.amount);

View File

@ -938,7 +938,7 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
return Wallet.getWalletByUser({ user_id: $scope.user.id }, function (wallet) {
const amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount);
if ((AuthService.isAuthorized(['member']) && amountToPay > 0) ||
if ((AuthService.isAuthorized(['member']) && (amountToPay > 0 || (amountToPay === 0 && hasOtherDeadlines()))) ||
(AuthService.isAuthorized('manager') && $scope.user.id === $rootScope.currentUser.id && amountToPay > 0)) {
return payByStripe(reservation);
} else {

View File

@ -47,15 +47,18 @@ Application.Directives.directive('coupon', [ '$rootScope', 'Coupon', '_t', funct
$scope.messages = [];
if ($scope.couponCode === '') {
$scope.status = 'pending';
return $scope.coupon = null;
$scope.coupon = null;
} else {
return Coupon.validate({ code: $scope.couponCode, user_id: $scope.userId, amount: $scope.total }, function (res) {
Coupon.validate({ code: $scope.couponCode, user_id: $scope.userId, amount: $scope.total }, function (res) {
$scope.status = 'valid';
$scope.coupon = res;
if (res.type === 'percent_off') {
return $scope.messages.push({ type: 'success', message: _t('app.shared.coupon_input.the_coupon_has_been_applied_you_get_PERCENT_discount', { PERCENT: res.percent_off }) });
$scope.messages.push({ type: 'success', message: _t('app.shared.coupon_input.the_coupon_has_been_applied_you_get_PERCENT_discount', { PERCENT: res.percent_off }) });
} else {
return $scope.messages.push({ type: 'success', message: _t('app.shared.coupon_input.the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY', { AMOUNT: res.amount_off, CURRENCY: $rootScope.currencySymbol }) });
$scope.messages.push({ type: 'success', message: _t('app.shared.coupon_input.the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY', { AMOUNT: res.amount_off, CURRENCY: $rootScope.currencySymbol }) });
}
if (res.validity_per_user === 'once') {
$scope.messages.push({ type: 'warning', message: _t('app.shared.coupon_input.coupon_validity_once') });
}
}
, function (err) {

View File

@ -1,7 +1,24 @@
export enum PaymentScheduleItemState {
New = 'new',
Pending = 'pending',
RequirePaymentMethod = 'requires_payment_method',
RequireAction = 'requires_action',
Paid = 'paid',
Error = 'error'
}
export enum PaymentMethod {
Stripe = 'stripe',
Check = 'check'
}
export interface PaymentScheduleItem {
id: number,
amount: number,
due_date: Date
due_date: Date,
state: PaymentScheduleItemState,
invoice_id: number,
payment_method: PaymentMethod,
client_secret?: string,
details: {
recurring: number,
adjustment: number,
@ -18,5 +35,25 @@ export interface PaymentSchedule {
reference: string,
payment_method: string,
wallet_amount: number,
items: Array<PaymentScheduleItem>
items: Array<PaymentScheduleItem>,
created_at: Date,
chained_footprint: boolean,
user: {
name: string
},
operator: {
id: number,
first_name: string,
last_name: string,
}
}
export interface PaymentScheduleIndexRequest {
query: {
reference?: string,
customer?: string,
date?: Date,
page: number,
size: number
}
}

View File

@ -1,4 +1,5 @@
import { Reservation } from './reservation';
import { SubscriptionRequest } from './subscription';
export interface PaymentConfirmation {
requires_action?: boolean,
@ -20,11 +21,6 @@ export enum PaymentMethod {
export interface CartItems {
reservation?: Reservation,
subscription?: {
plan_id: number,
user_id: number,
payment_schedule: boolean,
payment_method: PaymentMethod
},
subscription?: SubscriptionRequest,
coupon_code?: string
}

View File

@ -0,0 +1,18 @@
import { Plan } from './plan';
import { PaymentMethod } from './payment';
export interface Subscription {
id: number,
plan_id: number,
expired_at: Date,
canceled_at?: Date,
stripe: boolean,
plan: Plan
}
export interface SubscriptionRequest {
plan_id: number,
user_id: number,
payment_schedule: boolean,
payment_method: PaymentMethod
}

View File

@ -25,5 +25,9 @@
@import "modules/payment-schedule-summary";
@import "modules/wallet-info";
@import "modules/stripe-modal";
@import "modules/labelled-input";
@import "modules/document-filters";
@import "modules/payment-schedules-table";
@import "modules/payment-schedules-list";
@import "app.responsive";

View File

@ -0,0 +1,8 @@
.document-filters {
display: flex;
justify-content: space-between;
& > * {
width: 31%;
}
}

View File

@ -17,6 +17,8 @@
bottom: 0;
background-color: rgba(0, 0, 0, 0.9);
animation: 0.15s linear fadeIn;
overflow-x: hidden;
overflow-y: auto;
}
.fab-modal-sm { width: 340px; }

View File

@ -0,0 +1,48 @@
.input-with-label {
position: relative;
display: inline-table;
border-collapse: separate;
box-sizing: border-box;
label.label {
padding: 6px 12px;
font-size: 16px;
font-weight: 400;
line-height: 1;
color: #555555;
text-align: center;
background-color: #eeeeee;
border: 1px solid #c4c4c4;
border-radius: 4px 0 0 4px;
width: 1%;
white-space: nowrap;
vertical-align: middle;
display: table-cell;
box-sizing: border-box;
border-right: 0;
}
input.input {
padding: 6px 12px;
height: 38px;
font-size: 16px;
line-height: 1.5;
border: 1px solid #c4c4c4;
border-radius: 0 4px 4px 0;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
display: table-cell;
position: relative;
z-index: 2;
float: left;
width: 100%;
margin: 0;
box-sizing: border-box;
&:focus {
border-color: #fdde3f;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(253, 222, 63, .6);
}
}
}

View File

@ -0,0 +1,3 @@
.schedules-filters {
margin-bottom: 2em;
}

View File

@ -0,0 +1,156 @@
.schedules-table {
table-layout: fixed;
border: 1px solid #e9e9e9;
border-top: 0;
margin-bottom: 0;
width: 100%;
max-width: 100%;
background-color: transparent;
border-collapse: collapse;
border-spacing: 0;
& > thead {
border-top: 1px solid #e9e9e9;
& > tr > th {
font-weight: 600;
vertical-align: middle;
text-align: center;
padding: 2rem 1rem;
line-height: 1.5;
border: 1px solid #f0f0f0;
border-top: 0;
}
}
.w-35 { width: 35px; }
.w-120 { width: 120px; }
.w-200 { width: 200px; }
.schedules-table-body {
table-layout: fixed;
background-color: #fff;
border: 1px solid #e9e9e9;
border-top: 0;
margin-bottom: 0;
width: 100%;
max-width: 100%;
border-collapse: collapse;
border-spacing: 0;
& > tbody {
background: #f7f7f9;
border-collapse: collapse;
border-spacing: 0;
line-height: 1.5;
& > tr > td {
padding: 12px 10px;
border: 1px solid #f0f0f0;
border-top: 0;
vertical-align: middle;
font-size: 1.4rem;
line-height: 1.5;
&.row-header {
text-align: center;
cursor: pointer;
}
}
.schedule-items-table {
table-layout: fixed;
background-color: #fff;
width: 100%;
max-width: 100%;
margin-bottom: 1rem;
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #e9e9e9;
border-top: 0;
& > thead {
border-top: 1px solid #e9e9e9;
font-size: 1.4rem;
line-height: 1.5;
& > tr > th {
border: 1px solid #f0f0f0;
border-top: 0;
border-bottom: 1px solid #e9e9e9;
font-weight: 600;
vertical-align: middle;
text-align: center;
font-size: 1.1rem;
padding: 2rem 1rem;
text-transform: uppercase;
}
}
& > tbody > tr > td {
vertical-align: middle;
border: 1px solid #f0f0f0;
border-top: 0;
padding: 12px 10px;
font-size: 1.4rem;
line-height: 1.5;
}
}
}
}
.download-button,
.action-button {
color: black;
background-color: #fbfbfb;
display: inline-block;
margin-bottom: 0;
font-weight: normal;
text-align: center;
white-space: nowrap;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid #c9c9c9;
padding: 6px 12px;
font-size: 16px;
line-height: 1.5;
border-radius: 4px;
user-select: none;
text-decoration: none;
&:hover {
background-color: #f2f2f2;
color: black;
border-color: #aaaaaa;
text-decoration: none;
}
&:active {
color: black;
background-color: #f2f2f2;
border-color: #aaaaaa;
outline: 0;
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
& > i {
margin-right: 0.5em;
}
}
// The color classes above are automatically generated from PaymentScheduleItem.state
.state-new {
color: #3a3a3a;
}
.state-pending,
.state-requires_payment_method,
.state-requires_action {
color: #d43333;
}
.state-paid,
.state-error {
color: black;
}
}

View File

@ -79,6 +79,8 @@
</select>
<span class="help-block error" ng-show="couponForm['coupon[validity_per_user]'].$dirty && couponForm['coupon[validity_per_user]'].$error.required" translate>{{ 'app.shared.coupon.validity_per_user_is_required' }}</span>
</div>
<p class="alert alert-warning" ng-show="coupon.validity_per_user == 'once'" translate>{{ 'app.shared.coupon.warn_validity_once' }}</p>
<p class="alert alert-warning" ng-show="coupon.validity_per_user == 'forever'" translate>{{ 'app.shared.coupon.warn_validity_forever' }}</p>
<div class="form-group" ng-class="{'has-error': errors['valid_until']}">
<label for="coupon[valid_until]" translate>{{ 'app.shared.coupon.valid_until' }}</label>

View File

@ -34,6 +34,10 @@
<ng-include src="'/admin/invoices/list.html'"></ng-include>
</uib-tab>
<uib-tab heading="{{ 'app.admin.invoices.payment_schedules_list' | translate }}" ng-show="$root.modules.invoicing" index="4">
<payment-schedules-list />
</uib-tab>
<uib-tab heading="{{ 'app.admin.invoices.invoicing_settings' | translate }}" index="1" class="invoices-settings">
<ng-include src="'/admin/invoices/settings.html'"></ng-include>
</uib-tab>

View File

@ -1,7 +1,7 @@
<div class="" id="loginModal">
<div class="modal-header">
<img ng-src="{{logoBlack.custom_asset_file_attributes.attachment_url}}" alt="{{logo.custom_asset_file_attributes.attachment}}" class="modal-logo"/>
<h1 translate>
<h1 translate translate-default="Login">
{{ 'app.public.common.connection' }}
</h1>
</div>
@ -24,7 +24,7 @@
required="required"
ng-blur="emailError = !!loginForm.email.$error.email"
ng-focus="emailError = false"
placeholder="{{ 'app.public.common.your_email_address' | translate }}" />
translate-attr="{ placeholder: 'app.public.common.your_email_address' }" />
</div>
</div>
</div>
@ -38,12 +38,12 @@
class="form-control"
ng-model="user.password"
required="required"
placeholder="{{ 'app.public.common.your_password' | translate }}"
translate-attr="{ placeholder: 'app.public.common.your_password' }"
ng-minlength="8"/>
</div>
<a href="#" ng-click="openResetPassword($event)" class="text-xs">{{ 'app.public.common.password_forgotten' | translate }}</a>
<a href="#" ng-click="openResetPassword($event)" class="text-xs" translate translate-default="Forgotten password">{{ 'app.public.common.password_forgotten' }}</a>
<span ng-if="confirmationRequired">
<br><a href="#" ng-click="openConfirmationNewModal($event)" class="text-xs">{{ 'app.public.common.confirm_my_account' | translate }}</a>
<br><a href="#" ng-click="openConfirmationNewModal($event)" class="text-xs" translate translate-default="Confirm account">{{ 'app.public.common.confirm_my_account' }}</a>
</span>
<div class="alert alert-warning m-t-sm m-b-none text-xs p-sm" ng-show='isCapsLockOn' role="alert">
<i class="fa fa-warning"></i>
@ -56,13 +56,13 @@
</div>
<div class="panel-footer no-padder">
<button class="btn btn-valid btn-warning btn-block p-l btn-lg text-u-c r-b" ng-click="login()" ng-disabled="loginForm.$invalid" translate>{{ 'app.shared.buttons.confirm' }}</button>
<button class="btn btn-valid btn-warning btn-block p-l btn-lg text-u-c r-b" ng-click="login()" ng-disabled="loginForm.$invalid" translate translate-default="OK">{{ 'app.shared.buttons.confirm' }}</button>
</div>
</div>
<p class="text-center font-sbold">
<span translate>{{ 'app.public.common.not_registered_to_the_fablab' }}</span>
<span translate translate-default="Not registered?">{{ 'app.public.common.not_registered_to_the_fablab' }}</span>
<br/>
<a href="#" ng-click="openSignup($event)" class="text-u-l" translate>{{ 'app.public.common.create_an_account' }}</a></br>
<a href="#" ng-click="openSignup($event)" class="text-u-l" translate translate-default="Create an account">{{ 'app.public.common.create_an_account' }}</a></br>
</p>
</div>

View File

@ -41,7 +41,7 @@
</div>
<div class="row">
<wallet-info current-user="currentUser"
reservation="reservation"
cart-items="cartItems"
price="price"
wallet="wallet"/>
</div>

View File

@ -12,7 +12,7 @@
<div class="row">
<wallet-info current-user="currentUser"
reservation="reservation"
cart-items="cartItems"
price="price"
wallet="wallet"/>
</div>

View File

@ -17,6 +17,9 @@
<a ng-href="api/invoices/{{t.invoice.id}}/download" target="_blank" ng-if="t.invoice.id">
{{::t.invoice.reference}}
</a>
<a ng-href="api/payment_schedules/{{t.payment_schedule.id}}/download" target="_blank" ng-if="t.payment_schedule.id">
{{::t.payment_schedule.reference}}
</a>
</td>
<td>{{ ::t.user.full_name }}</td>
<td ng-class="{'green':t.transaction_type == 'credit', 'red':t.transaction_type == 'debit'}">

View File

@ -43,4 +43,11 @@ class NotificationsMailer < NotifyWith::NotificationsMailer
subject: t('notifications_mailer.notify_member_avoir_ready.subject'),
template_name: 'notify_member_avoir_ready')
end
def notify_user_when_payment_schedule_ready
attachments[@attached_object.filename] = File.read(@attached_object.file)
mail(to: @recipient.email,
subject: t('notifications_mailer.notify_member_payment_schedule_ready.subject'),
template_name: 'notify_member_payment_schedule_ready')
end
end

View File

@ -5,7 +5,7 @@ class Coupon < ApplicationRecord
has_many :invoices
has_many :payment_schedule
after_commit :create_stripe_coupon, on: [:create]
after_save :create_stripe_coupon, on: [:create]
after_commit :delete_stripe_coupon, on: [:destroy]
validates :name, presence: true
@ -32,13 +32,17 @@ class Coupon < ApplicationRecord
}
def safe_destroy
if invoices.size.zero?
if usages.zero?
destroy
else
false
end
end
def usages
invoices.count + payment_schedule.count
end
##
# Check the status of the current coupon. The coupon:
# - may have been disabled by an admin,
@ -94,7 +98,7 @@ class Coupon < ApplicationRecord
private
def create_stripe_coupon
StripeWorker.perform_async(:create_stripe_coupon, id)
StripeService.create_stripe_coupon(id)
end
def delete_stripe_coupon

View File

@ -54,6 +54,10 @@ class NotificationType
notify_admins_role_update
notify_user_role_update
notify_admin_members_stripe_sync
notify_user_when_payment_schedule_ready
notify_admin_payment_schedule_failed
notify_member_payment_schedule_failed
notify_admin_payment_schedule_check_deadline
]
# deprecated:
# - notify_member_subscribed_plan_is_changed

View File

@ -18,9 +18,9 @@ class PaymentDocument < Footprintable
end
def set_wallet_transaction(amount, transaction_id)
raise InvalidFootprintError unless check_footprint
update_columns(wallet_amount: amount, wallet_transaction_id: transaction_id)
chain_record
self.wallet_amount = amount
self.wallet_transaction_id = transaction_id
end
def post_save(arg); end
end

View File

@ -9,6 +9,7 @@ class PaymentSchedule < PaymentDocument
belongs_to :wallet_transaction
belongs_to :coupon
belongs_to :invoicing_profile
belongs_to :statistic_profile
belongs_to :operator_profile, foreign_key: :operator_profile_id, class_name: 'InvoicingProfile'
belongs_to :subscription, foreign_type: 'Subscription', foreign_key: 'scheduled_id'
@ -19,6 +20,7 @@ class PaymentSchedule < PaymentDocument
before_create :add_environment
after_create :update_reference, :chain_record
after_commit :generate_and_send_document, on: [:create], if: :persisted?
after_commit :generate_initial_invoice, on: [:create], if: :persisted?
def file
dir = "payment_schedules/#{invoicing_profile.id}"
@ -45,10 +47,24 @@ class PaymentSchedule < PaymentDocument
payment_schedule_items.order(due_date: :asc)
end
def user
invoicing_profile.user
end
def check_footprint
payment_schedule_items.map(&:check_footprint).all? && footprint == compute_footprint
end
def post_save(setup_intent_id)
return unless payment_method == 'stripe'
StripeService.create_stripe_subscription(self, setup_intent_id)
end
def self.columns_out_of_footprint
%w[stp_subscription_id]
end
private
def generate_and_send_document
@ -60,4 +76,8 @@ class PaymentSchedule < PaymentDocument
end
PaymentScheduleWorker.perform_async(id)
end
def generate_initial_invoice
PaymentScheduleItemWorker.perform_async
end
end

View File

@ -6,7 +6,19 @@ class PaymentScheduleItem < Footprintable
belongs_to :invoice
after_create :chain_record
def first?
payment_schedule.ordered_items.first == self
end
def payment_intent
return unless stp_invoice_id
key = Setting.get('stripe_secret_key')
stp_invoice = Stripe::Invoice.retrieve(stp_invoice_id, api_key: key)
Stripe::PaymentIntent.retrieve(stp_invoice.payment_intent, api_key: key)
end
def self.columns_out_of_footprint
%w[invoice_id]
%w[invoice_id stp_invoice_id state payment_method]
end
end

View File

@ -145,15 +145,13 @@ class Price < ApplicationRecord
total_amount = cs.apply(total_amount, cp)
# == generate PaymentSchedule (if applicable) ===
schedule = if options[:payment_schedule] && plan.monthly_payment
PaymentScheduleService.new.compute(plan, _amount_no_coupon, cp)
schedule = if options[:payment_schedule] && plan&.monthly_payment
PaymentScheduleService.new.compute(plan, _amount_no_coupon, coupon: cp)
else
nil
end
if schedule
total_amount -= schedule[:payment_schedule].total
total_amount += schedule[:items][0].amount
end
total_amount = schedule[:items][0].amount if schedule
# return result
{

View File

@ -45,9 +45,7 @@ class Reservation < ApplicationRecord
def generate_subscription
return unless plan_id
self.subscription = Subscription.find_or_initialize_by(statistic_profile_id: statistic_profile_id)
subscription.attributes = { plan_id: plan_id, statistic_profile_id: statistic_profile_id, expiration_date: nil }
self.subscription = Subscription.new(plan_id: plan_id, statistic_profile_id: statistic_profile_id, expiration_date: nil)
subscription.init_save
subscription
end

View File

@ -148,7 +148,7 @@ class Setting < ApplicationRecord
##
# Return the value of the requested setting, if any.
# Usage: Setting.get('my_setting')
# @return {String}
# @return {String|Boolean}
##
def self.get(name)
res = find_by(name: name)&.value

View File

@ -38,6 +38,7 @@ class Subscription < ApplicationRecord
end
def cancel
# TODO, currently unused, refactor to use with PaymentSchedule
update_columns(canceled_at: DateTime.current)
end
@ -143,18 +144,4 @@ class Subscription < ApplicationRecord
def of_partner_plan?
plan.is_a?(PartnerPlan)
end
def get_wallet_amount_debit
total = plan.amount
total = CouponService.new.apply(total, @coupon, user.id) if @coupon
wallet_amount = (user.wallet.amount * 100).to_i
wallet_amount >= total ? total : wallet_amount
end
def debit_user_wallet
return if !@wallet_amount_debit.present? || @wallet_amount_debit.zero?
amount = @wallet_amount_debit / 100.0
WalletService.new(user: user, wallet: user.wallet).debit(amount, self)
end
end

View File

@ -0,0 +1,151 @@
# frozen_string_literal: true
# Generate a downloadable PDF file for the recorded payment schedule
class PDF::PaymentSchedule < Prawn::Document
require 'stringio'
include ActionView::Helpers::NumberHelper
include ApplicationHelper
##
# @param payment_schedule {PaymentSchedule}
##
def initialize(payment_schedule)
super(margin: 70)
# fonts
opensans = Rails.root.join('vendor/assets/fonts/OpenSans-Regular.ttf').to_s
opensans_bold = Rails.root.join('vendor/assets/fonts/OpenSans-Bold.ttf').to_s
opensans_bolditalic = Rails.root.join('vendor/assets/fonts/OpenSans-BoldItalic.ttf').to_s
opensans_italic = Rails.root.join('vendor/assets/fonts/OpenSans-Italic.ttf').to_s
font_families.update(
'Open-Sans' => {
normal: { file: opensans, font: 'Open-Sans' },
bold: { file: opensans_bold, font: 'Open-Sans-Bold' },
italic: { file: opensans_italic, font: 'Open-Sans-Oblique' },
bold_italic: { file: opensans_bolditalic, font: 'Open-Sans-BoldOblique' }
}
)
# logo
img_b64 = Setting.find_by(name: 'invoice_logo')
begin
image StringIO.new(Base64.decode64(img_b64.value)), fit: [415, 40]
rescue StandardError => e
puts "Unable to decode invoice logo from base64: #{e}"
end
move_down 20
font('Open-Sans', size: 10) do
# general information
text I18n.t('payment_schedules.schedule_reference', REF: payment_schedule.reference), leading: 3
text I18n.t('payment_schedules.schedule_issued_on_DATE', DATE: I18n.l(payment_schedule.created_at.to_date))
# user/organization's information
if payment_schedule.invoicing_profile&.organization
name = payment_schedule.invoicing_profile.organization.name
full_name = "#{name} (#{payment_schedule.invoicing_profile.full_name})"
else
name = payment_schedule.invoicing_profile.full_name
full_name = name
end
address = if payment_schedule.invoicing_profile&.organization&.address
payment_schedule.invoicing_profile.organization.address.address
elsif payment_schedule.invoicing_profile&.address
payment_schedule.invoicing_profile.address.address
else
''
end
text_box "<b>#{name}</b>\n#{payment_schedule.invoicing_profile.email}\n#{address}",
at: [bounds.width - 130, bounds.top - 49],
width: 130,
align: :right,
inline_format: true
name = full_name
subscription = Subscription.find(payment_schedule.payment_schedule_items.first.details['subscription_id'])
# object
move_down 25
text I18n.t('payment_schedules.object', ITEM: subscription_verbose(subscription, name))
# details table of the deadlines
move_down 20
text I18n.t('payment_schedules.deadlines'), leading: 4
move_down 2
data = [[I18n.t('payment_schedules.deadline_date'), I18n.t('payment_schedules.deadline_amount')]]
# going through the payment_schedule_items
payment_schedule.payment_schedule_items.each do |item|
price = item.amount.to_i / 100.00
date = I18n.l(item.due_date.to_date)
data += [[date, number_to_currency(price)]]
end
data += [[I18n.t('payment_schedules.total_amount'), number_to_currency(payment_schedule.total / 100.0)]]
# display table
font_size(8) do
table(data, header: true, column_widths: [400, 72], cell_style: { inline_format: true }) do
row(0).font_style = :bold
column(1).style align: :right
row(-1).style align: :right
row(-1).background_color = 'E4E4E4'
row(-1).font_style = :bold
end
end
# payment method
move_down 20
payment_verbose = _t('payment_schedules.settlement_by_METHOD', METHOD: payment_schedule.payment_method)
payment_verbose = I18n.t('payment_schedules.settlement_by_wallet', AMOUNT: payment_schedule.wallet_amount / 100.00) if payment_schedule.wallet_amount
text payment_verbose
# important information
move_down 40
txt = parse_html(Setting.get('invoice_text'))
txt.each_line do |line|
text line, style: :bold, inline_format: true
end
# address and legals information
move_down 40
txt = parse_html(Setting.get('invoice_legals'))
txt.each_line do |line|
text line, align: :right, leading: 4, inline_format: true
end
end
# factice watermark
return unless %w[staging test development].include?(payment_schedule.environment)
transparent(0.1) do
rotate(45, origin: [0, 0]) do
image "#{Rails.root}/app/pdfs/data/watermark-#{I18n.locale}.png", at: [90, 150]
end
end
end
private
def subscription_verbose(subscription, username)
subscription_start_at = subscription.expired_at - subscription.plan.duration
duration_verbose = I18n.t("duration.#{subscription.plan.interval}", count: subscription.plan.interval_count)
I18n.t('payment_schedules.subscription_of_NAME_for_DURATION_starting_from_DATE',
NAME: username,
DURATION: duration_verbose,
DATE: I18n.l(subscription_start_at.to_date))
end
##
# Remove every unsupported html tag from the given html text (like <p>, <span>, ...).
# The supported tags are <b>, <u>, <i> and <br>.
# @param html [String] single line html text
# @return [String] multi line simplified html text
##
def parse_html(html)
ActionController::Base.helpers.sanitize(html, tags: %w[b u i br])
end
end

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
# Check the access policies for API::PaymentSchedulesController
class PaymentSchedulePolicy < ApplicationPolicy
def list?
user.admin? || user.manager?
end
def download?
user.admin? || user.manager? || (record.invoicing_profile.user_id == user.id)
end
end

View File

@ -2,7 +2,8 @@
# Provides helper methods for Events resources and properties
class EventService
def self.process_params(params)
class << self
def process_params(params)
# handle dates & times (whole-day events or not, maybe during many days)
range = EventService.date_range({ date: params[:start_date], time: params[:start_time] },
{ date: params[:end_date], time: params[:end_time] },
@ -27,7 +28,7 @@ class EventService
params
end
def self.date_range(starting, ending, all_day)
def date_range(starting, ending, all_day)
start_date = Time.zone.parse(starting[:date])
end_date = Time.zone.parse(ending[:date])
start_time = Time.parse(starting[:time]) if starting[:time]
@ -43,7 +44,7 @@ class EventService
end
# delete one or more events (if periodic)
def self.delete(event_id, mode = 'single')
def delete(event_id, mode = 'single')
results = []
event = Event.find(event_id)
events = case mode
@ -74,8 +75,7 @@ class EventService
end
# update one or more events (if periodic)
def self.update(event, event_params, mode = 'single')
results = []
def update(event, event_params, mode = 'single')
events = case mode
when 'single'
[event]
@ -96,7 +96,13 @@ class EventService
else
[]
end
update_events(event, events, event_params)
end
private
def update_events(event, events, event_params)
results = []
events.each do |e|
next unless e.id != event.id
@ -162,12 +168,26 @@ class EventService
rescue StandardError => err
results.push status: false, event: e, error: err.try(:record).try(:class).try(:name), message: err.message
end
results.concat(update_slots(e.availability_id))
end
begin
results.push status: !!event.update(event_params), event: event # rubocop:disable Style/DoubleNegation
rescue StandardError => err
results.push status: false, event: event, error: err.try(:record).try(:class).try(:name), message: err.message
end
results.concat(update_slots(event.availability_id))
results
end
def update_slots(availability_id)
results = []
avail = Availability.find(availability_id)
avail.slots.each do |s|
results.push(status: !!s.update_attributes(start_at: avail.start_at, end_at: avail.end_at), slot: s) # rubocop:disable Style/DoubleNegation
rescue StandardError => err
results.push status: false, slot: s, error: err.try(:record).try(:class).try(:name), message: err.message
end
results
end
end
end

View File

@ -87,9 +87,10 @@ class PaymentDocumentService
else
return get_max_id(Invoice) + get_max_id(PaymentSchedule)
end
return Invoice.count unless defined? start && defined? ending
return Invoice.count + PaymentSchedule.count unless defined? start && defined? ending
Invoice.where('created_at >= :start_date AND created_at < :end_date', start_date: start, end_date: ending).length
Invoice.where('created_at >= :start_date AND created_at < :end_date', start_date: start, end_date: ending).length +
PaymentSchedule.where('created_at >= :start_date AND created_at < :end_date', start_date: start, end_date: ending).length
end
##

View File

@ -8,34 +8,36 @@ class PaymentScheduleService
# @param total {Number} Total amount of the current shopping cart (which includes this plan) - without coupon
# @param coupon {Coupon} apply this coupon, if any
##
def compute(plan, total, coupon = nil)
def compute(plan, total, coupon: nil, subscription: nil)
other_items = total - plan.amount
price = if coupon
cs = CouponService.new
other_items = cs.ventilate(total, other_items, coupon)
cs.ventilate(total, plan.amount, coupon)
else
plan.amount
end
# base monthly price of the plan
price = plan.amount
ps = PaymentSchedule.new(scheduled: plan, total: price + other_items, coupon: coupon)
deadlines = plan.duration / 1.month
per_month = (price / deadlines).truncate
adjustment = if per_month * deadlines != price
price - (per_month * deadlines)
adjustment = if per_month * deadlines + other_items.truncate != ps.total
ps.total - (per_month * deadlines + other_items.truncate)
else
0
end
items = []
(0..deadlines - 1).each do |i|
date = DateTime.current + i.months
details = { recurring: per_month }
details = { recurring: per_month, subscription_id: subscription&.id }
amount = if i.zero?
details[:adjustment] = adjustment
details[:other_items] = other_items
per_month + adjustment + other_items
details[:adjustment] = adjustment.truncate
details[:other_items] = other_items.truncate
per_month + adjustment.truncate + other_items.truncate
else
per_month
end
if coupon
cs = CouponService.new
if (coupon.validity_per_user == 'once' && i.zero?) || coupon.validity_per_user == 'forever'
details[:without_coupon] = amount
amount = cs.apply(amount, coupon)
end
end
items.push PaymentScheduleItem.new(
amount: amount,
due_date: date,
@ -43,13 +45,15 @@ class PaymentScheduleService
details: details
)
end
ps.total = items.map(&:amount).reduce(:+)
{ payment_schedule: ps, items: items }
end
def create(subscription, total, coupon: nil, operator: nil, payment_method: nil, reservation: nil, user: nil, setup_intent_id: nil)
subscription = reservation.generate_subscription if !subscription && reservation.plan_id
subscription = reservation.generate_subscription if !subscription && reservation&.plan_id
raise InvalidSubscriptionError unless subscription&.persisted?
schedule = compute(subscription.plan, total, coupon)
schedule = compute(subscription.plan, total, coupon: coupon, subscription: subscription)
ps = schedule[:payment_schedule]
items = schedule[:items]
@ -58,13 +62,178 @@ class PaymentScheduleService
ps.stp_setup_intent_id = setup_intent_id
ps.operator_profile = operator.invoicing_profile
ps.invoicing_profile = user.invoicing_profile
ps.save!
ps.statistic_profile = user.statistic_profile
ps.payment_schedule_items = items
items.each do |item|
item.payment_schedule = ps
item.save!
end
StripeService.create_stripe_subscription(ps.id, subscription, reservation&.reservable&.stp_product_id, setup_intent_id) if payment_method == 'stripe'
ps
end
##
# Generate the invoice associated with the given PaymentScheduleItem, with the children elements (InvoiceItems).
# @param stp_invoice is used to determine if the invoice was paid using stripe
##
def generate_invoice(payment_schedule_item, stp_invoice = nil)
# build the base invoice
invoice = Invoice.new(
invoiced: payment_schedule_item.payment_schedule.scheduled,
invoicing_profile: payment_schedule_item.payment_schedule.invoicing_profile,
statistic_profile: payment_schedule_item.payment_schedule.statistic_profile,
operator_profile_id: payment_schedule_item.payment_schedule.operator_profile_id,
stp_payment_intent_id: stp_invoice&.payment_intent,
payment_method: stp_invoice ? 'stripe' : nil
)
# complete the invoice with some InvoiceItem
if payment_schedule_item.first?
complete_first_invoice(payment_schedule_item, invoice)
else
complete_next_invoice(payment_schedule_item, invoice)
end
# set the total and apply any coupon
user = payment_schedule_item.payment_schedule.user
coupon = payment_schedule_item.payment_schedule.coupon
set_total_and_coupon(payment_schedule_item, invoice, user, coupon)
# save the results
invoice.save
payment_schedule_item.update_attributes(invoice_id: invoice.id)
end
##
# return a paginated list of PaymentSchedule, optionally filtered, with their associated PaymentScheduleItem
# @param page {number} page number, used to paginate results
# @param size {number} number of items per page
# @param filters {Hash} allowed filters: reference, customer, date.
##
def self.list(page, size, filters = {})
ps = PaymentSchedule.includes(:invoicing_profile, :payment_schedule_items, :subscription)
.joins(:invoicing_profile)
.order('payment_schedules.created_at DESC')
.page(page)
.per(size)
unless filters[:reference].nil?
ps = ps.where(
'payment_schedules.reference LIKE :search',
search: "#{filters[:reference]}%"
)
end
unless filters[:customer].nil?
# ILIKE => PostgreSQL case-insensitive LIKE
ps = ps.where(
'invoicing_profiles.first_name ILIKE :search OR invoicing_profiles.last_name ILIKE :search',
search: "%#{filters[:customer]}%"
)
end
unless filters[:date].nil?
ps = ps.where(
"date_trunc('day', payment_schedules.created_at) = :search OR date_trunc('day', payment_schedule_items.due_date) = :search",
search: "%#{DateTime.iso8601(filters[:date]).to_time.to_date}%"
)
end
ps
end
private
##
# The first PaymentScheduleItem contains references to the reservation price (if any) and to the adjustement price
# for the subscription (if any)
##
def complete_first_invoice(payment_schedule_item, invoice)
# sub-prices for the subscription and the reservation
details = {
subscription: payment_schedule_item.details['recurring'] + payment_schedule_item.details['adjustment']
}
# the subscription and reservation items
subscription = Subscription.find(payment_schedule_item.details['subscription_id'])
if payment_schedule_item.payment_schedule.scheduled_type == Reservation.name
details[:reservation] = payment_schedule_item.details['other_items']
reservation = payment_schedule_item.payment_schedule.scheduled
end
# build the invoice items
generate_invoice_items(invoice, details, subscription: subscription, reservation: reservation)
end
##
# The later PaymentScheduleItems only contain references to the subscription (which is recurring)
##
def complete_next_invoice(payment_schedule_item, invoice)
# the subscription item
subscription = Subscription.find(payment_schedule_item.details['subscription_id'])
# sub-price for the subscription
details = { subscription: payment_schedule_item.details['recurring'] }
# build the invoice item
generate_invoice_items(invoice, details, subscription: subscription)
end
##
# Generate an array of InvoiceItem according to the provided parameters and saves them in invoice.invoice_items
##
def generate_invoice_items(invoice, payment_details, reservation: nil, subscription: nil)
generate_reservation_item(invoice, reservation, payment_details) if reservation
return unless subscription
generate_subscription_item(invoice, subscription, payment_details)
end
##
# Generate a single InvoiceItem for the given reservation and save it in invoice.invoice_items.
# This method must be called only with a valid reservation
##
def generate_reservation_item(invoice, reservation, payment_details)
raise TypeError unless [Space, Machine, Training].include? reservation.reservable.class
description = "#{reservation.reservable.name}\n"
reservation.slots.each do |slot|
description += " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}\n"
end
invoice.invoice_items.push InvoiceItem.new(
amount: payment_details[:reservation],
description: description
)
end
##
# Generate an InvoiceItem for the given subscription and save it in invoice.invoice_items.
# This method must be called only with a valid subscription
##
def generate_subscription_item(invoice, subscription, payment_details)
raise TypeError unless subscription
invoice.invoice_items.push InvoiceItem.new(
amount: payment_details[:subscription],
description: subscription.plan.name,
subscription_id: subscription.id
)
end
##
# Set the total price to the invoice, summing all sub-items.
# Additionally a coupon may be applied to this invoice to make a discount on the total price
##
def set_total_and_coupon(payment_schedule_item, invoice, user, coupon = nil)
return unless invoice
total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+)
unless coupon.nil?
if (coupon.validity_per_user == 'once' && payment_schedule_item.first?) || coupon.validity_per_user == 'forever'
total = CouponService.new.apply(total, coupon, user.id)
invoice.coupon_id = coupon.id
end
end
invoice.total = total
end
end

View File

@ -25,15 +25,16 @@ class Reservations::Reserve
operator_profile_id: operator_profile_id,
user: user,
payment_method: payment_method,
coupon_code: payment_details[:coupon],
coupon: payment_details[:coupon],
setup_intent_id: intent_id)
else
generate_invoice(reservation, operator_profile_id, payment_details, intent_id)
end
payment.save
reservation.save
WalletService.debit_user_wallet(payment, user, reservation)
reservation.save
reservation.post_save
payment.save
payment.post_save(intent_id)
end
true
end
@ -43,10 +44,9 @@ class Reservations::Reserve
##
# Generate the invoice for the given reservation+subscription
##
def generate_schedule(reservation: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon_code: nil,
def generate_schedule(reservation: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon: nil,
setup_intent_id: nil)
operator = InvoicingProfile.find(operator_profile_id)&.user
coupon = Coupon.find_by(code: coupon_code) unless coupon_code.nil?
PaymentScheduleService.new.create(
nil,

View File

@ -5,11 +5,23 @@ class StripeService
class << self
# Create the provided PaymentSchedule on Stripe, using the Subscription API
def create_stripe_subscription(payment_schedule_id, subscription, reservable_stp_id, setup_intent_id)
def create_stripe_subscription(payment_schedule, setup_intent_id)
stripe_key = Setting.get('stripe_secret_key')
payment_schedule = PaymentSchedule.find(payment_schedule_id)
first_item = payment_schedule.ordered_items.first
case payment_schedule.scheduled_type
when Reservation.name
subscription = payment_schedule.scheduled.subscription
reservable_stp_id = payment_schedule.scheduled.reservable&.stp_product_id
when Subscription.name
subscription = payment_schedule.scheduled
reservable_stp_id = nil
else
raise InvalidSubscriptionError
end
handle_wallet_transaction(payment_schedule)
# setup intent (associates the customer and the payment method)
intent = Stripe::SetupIntent.retrieve(setup_intent_id, api_key: stripe_key)
# subscription (recurring price)
@ -22,8 +34,8 @@ class StripeService
stp_subscription = Stripe::Subscription.create({
customer: payment_schedule.invoicing_profile.user.stp_customer_id,
cancel_at: subscription.expiration_date.to_i,
promotion_code: payment_schedule.coupon&.code,
add_invoice_items: items,
coupon: payment_schedule.coupon&.code,
items: [
{ price: price[:id] }
],
@ -32,6 +44,23 @@ class StripeService
payment_schedule.update_attributes(stp_subscription_id: stp_subscription.id)
end
def create_stripe_coupon(coupon_id)
coupon = Coupon.find(coupon_id)
stp_coupon = { id: coupon.code }
if coupon.type == 'percent_off'
stp_coupon[:percent_off] = coupon.percent_off
elsif coupon.type == 'amount_off'
stp_coupon[:amount_off] = coupon.amount_off
stp_coupon[:currency] = Setting.get('stripe_currency')
end
stp_coupon[:duration] = coupon.validity_per_user == 'always' ? 'forever' : 'once'
stp_coupon[:redeem_by] = coupon.valid_until.to_i unless coupon.valid_until.nil?
stp_coupon[:max_redemptions] = coupon.max_usages unless coupon.max_usages.nil?
Stripe::Coupon.create(stp_coupon, api_key: Setting.get('stripe_secret_key'))
end
private
def subscription_invoice_items(payment_schedule, subscription, first_item, reservable_stp_id)
@ -71,5 +100,12 @@ class StripeService
Stripe::Price.create(params, api_key: Setting.get('stripe_secret_key'))
end
def handle_wallet_transaction(payment_schedule)
return unless payment_schedule.wallet_amount
customer_id = payment_schedule.invoicing_profile.user.stp_customer_id
Stripe::Customer.update(customer_id, { balance: -payment_schedule.wallet_amount }, { api_key: Setting.get('stripe_secret_key') })
end
end
end

View File

@ -24,19 +24,22 @@ class Subscriptions::Subscribe
ActiveRecord::Base.transaction do
subscription.init_save
raise InvalidSubscriptionError unless subscription&.persisted?
payment = if schedule
generate_schedule(subscription: subscription,
total: payment_details[:before_coupon],
operator_profile_id: operator_profile_id,
user: user,
payment_method: payment_method,
coupon_code: payment_details[:coupon],
coupon: payment_details[:coupon],
setup_intent_id: intent_id)
else
generate_invoice(subscription, operator_profile_id, payment_details, intent_id)
end
payment.save
WalletService.debit_user_wallet(payment, user, subscription)
payment.save
payment.post_save(intent_id)
end
true
end
@ -74,10 +77,9 @@ class Subscriptions::Subscribe
##
# Generate the invoice for the given subscription
##
def generate_schedule(subscription: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon_code: nil,
def generate_schedule(subscription: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon: nil,
setup_intent_id: nil)
operator = InvoicingProfile.find(operator_profile_id)&.user
coupon = Coupon.find_by(code: coupon_code) unless coupon_code.nil?
PaymentScheduleService.new.create(
subscription,

View File

@ -80,7 +80,11 @@ class WalletService
# @param coupon {Coupon|String} Coupon object or code
##
def self.wallet_amount_debit(payment, user, coupon = nil)
total = payment.total
total = if payment.class == PaymentSchedule
payment.payment_schedule_items.first.amount
else
payment.total
end
total = CouponService.new.apply(total, coupon, user.id) if coupon
wallet_amount = (user.wallet.amount * 100).to_i

View File

@ -1,4 +1,4 @@
json.extract! coupon, :id, :name, :code, :type, :percent_off, :valid_until, :validity_per_user, :max_usages, :active, :created_at
json.amount_off (coupon.amount_off / 100.00) unless coupon.amount_off.nil?
json.usages coupon.invoices.count
json.usages coupon.usages
json.status coupon.status

View File

@ -1,2 +1,4 @@
json.extract! @coupon, :id, :code, :type, :percent_off
# frozen_string_literal: true
json.extract! @coupon, :id, :code, :type, :percent_off, :validity_per_user
json.amount_off (@coupon.amount_off / 100.00) unless @coupon.amount_off.nil?

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
json.title notification.notification_type
json.description t('.schedule_deadline', DATE: I18n.l(notification.attached_object.due_date.to_date),
REFERENCE: notification.attached_object.payment_schedule.reference)

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
json.title notification.notification_type
json.description t('.schedule_failed', DATE: I18n.l(notification.attached_object.due_date.to_date),
REFERENCE: notification.attached_object.payment_schedule.reference)

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
json.title notification.notification_type
json.description t('.schedule_failed', DATE: I18n.l(notification.attached_object.due_date.to_date),
REFERENCE: notification.attached_object.payment_schedule.reference)

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
json.title notification.notification_type
amount = notification.attached_object.total / 100.0
json.description t('.your_schedule_is_ready_html',
REFERENCE: notification.attached_object.reference,
AMOUNT: number_to_currency(amount),
SCHEDULE_ID: notification.attached_object.id)

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
json.array! @payment_schedules do |ps|
json.extract! ps, :id, :reference, :created_at, :payment_method
json.total ps.total / 100.00
json.chained_footprint ps.check_footprint
json.user do
json.name ps.invoicing_profile.full_name
end
if ps.operator_profile
json.operator do
json.id ps.operator_profile.user_id
json.extract! ps.operator_profile, :first_name, :last_name
end
end
json.items ps.payment_schedule_items do |item|
json.extract! item, :id, :due_date, :state, :invoice_id, :payment_method
json.amount item.amount / 100.00
json.client_secret item.payment_intent.client_secret if item.stp_invoice_id && item.state == 'requires_action'
end
end

View File

@ -10,4 +10,10 @@ json.array!(@wallet_transactions) do |t|
json.reference t.invoice.reference
end
end
if t.payment_schedule
json.payment_schedule do
json.id t.payment_schedule.id
json.reference t.payment_schedule.reference
end
end
end

View File

@ -0,0 +1,10 @@
<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
<p>
<%= t('.body.remember',
REFERENCE: @attached_object.payment_schedule.reference,
AMOUNT: number_to_currency(@attached_object.amount),
DATE: I18n.l @attached_object.due_date, format: :long) %>
<%= t('.body.date') %>
</p>
<p><%= t('.body.confirm') %></p>

View File

@ -0,0 +1,10 @@
<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
<p>
<%= t('.body.remember',
REFERENCE: @attached_object.payment_schedule.reference,
AMOUNT: number_to_currency(@attached_object.amount),
DATE: I18n.l @attached_object.due_date, format: :long) %>
<%= t('.body.error') %>
</p>
<p><%= t('.body.action') %></p>

View File

@ -1,4 +1,4 @@
<%# this is a mail template of notifcation notify_admin_user_wallet_is_credited %>
<%# this is a mail template of notification notify_admin_user_wallet_is_credited %>
<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
<p>
<%= t('.body.wallet_credit_html',

View File

@ -0,0 +1,10 @@
<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
<p>
<%= t('.body.remember',
REFERENCE: @attached_object.payment_schedule.reference,
AMOUNT: number_to_currency(@attached_object.amount),
DATE: I18n.l @attached_object.due_date, format: :long) %>
<%= t('.body.error') %>
</p>
<p><%= t('.body.action') %></p>

View File

@ -0,0 +1,20 @@
<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
<p>
<%= _t('.body.please_find_attached_html',
{
DATE: I18n.l(@attached_object.created_at.to_date),
AMOUNT: number_to_currency(@attached_object.total / 100.0),
TYPE: @attached_object.scheduled_type
})
# messageFormat
%>
</p>
<p><%= t('.body.schedule_in_your_dashboard_html',
DASHBOARD: link_to(
t('.body.your_dashboard'),
"#{root_url}#!/dashboard/invoices"
)
) %>
</p>

View File

@ -1 +1,3 @@
# frozen_string_literal: true
json.extract! machine, :id, :name, :slug, :disabled, :updated_at, :created_at

View File

@ -0,0 +1,3 @@
# frozen_string_literal: true
json.partial! 'open_api/v1/machines/machine', machine: @machine

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
json.machines @machines do |machine|
json.partial! 'open_api/v1/machines/machine', machine: machine
json.extract! machine, :description, :spec

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
json.partial! 'open_api/v1/machines/machine', machine: @machine
json.extract! @machine, :description, :spec
json.image URI.join(root_url, @machine.machine_image.attachment.url) if @machine.machine_image

View File

@ -0,0 +1,3 @@
# frozen_string_literal: true
json.partial! 'open_api/v1/machines/machine', machine: @machine

View File

@ -6,19 +6,37 @@ class PaymentScheduleItemWorker
include Sidekiq::Worker
def perform
PaymentScheduleItem.where(due_date: [DateTime.current.at_beginning_of_day, DateTime.current.end_of_day], state: 'new').each do |psi|
PaymentScheduleItem.where(state: 'new').where('due_date < ?', DateTime.current.end_of_day).each do |psi|
# the following depends on the payment method (stripe/check)
if psi.payment_schedule.payment_method == 'stripe'
# TODO, if stripe:
# - verify the payment was successful
# - if not, alert the admins
# - if succeeded, generate the invoice
### Stripe
stripe_key = Setting.get('stripe_secret_key')
stp_suscription = Stripe::Subscription.retrieve(psi.payment_schedule.stp_subscription_id, api_key: stripe_key)
stp_invoice = Stripe::Invoice.retrieve(stp_suscription.latest_invoice, api_key: stripe_key)
if stp_invoice.status == 'paid'
##### Stripe / Successfully paid
PaymentScheduleService.new.generate_invoice(psi, stp_invoice)
psi.update_attributes(state: 'paid', payment_method: 'stripe', stp_invoice_id: stp_invoice.id)
elsif stp_suscription.status == 'past_due'
##### Stripe / Payment error
NotificationCenter.call type: 'notify_admin_payment_schedule_failed',
receiver: User.admins_and_managers,
attached_object: psi
NotificationCenter.call type: 'notify_member_payment_schedule_failed',
receiver: psi.payment_schedule.user,
attached_object: psi
stp_payment_intent = Stripe::PaymentIntent.retrieve(stp_invoice.payment_intent, api_key: stripe_key)
psi.update_attributes(state: stp_payment_intent.status, stp_invoice_id: stp_invoice.id)
else
# TODO, if check:
# - alert the admins and the user that it is time to bank the check
# - generate the invoice
psi.update_attributes(state: 'error')
end
else
### Check
NotificationCenter.call type: 'notify_admin_payment_schedule_check_deadline',
receiver: User.admins_and_managers,
attached_object: psi
psi.update_attributes(state: 'pending')
end
# TODO, finally, in any cases, update the psi.state field according to the new status
end
end
end

View File

@ -8,13 +8,13 @@ class PaymentScheduleWorker
def perform(payment_schedule_id)
# generate a payment schedule document
ps = PaymentSchedule.find(payment_schedule_id)
pdf = ::PDF::PaymentSchedule.new(ps).render # TODO, create ::PDF::PaymentSchedule
pdf = ::PDF::PaymentSchedule.new(ps).render
# save the file on the disk
File.binwrite(ps.file, pdf)
# notify user, send schedule document by email
NotificationCenter.call type: 'notify_user_when_invoice_ready', # TODO, create a more appropriate notification type
NotificationCenter.call type: 'notify_user_when_payment_schedule_ready',
receiver: ps.user,
attached_object: ps
end

View File

@ -21,28 +21,11 @@ class StripeWorker
user.update_columns(stp_customer_id: customer.id)
end
def create_stripe_coupon(coupon_id)
coupon = Coupon.find(coupon_id)
stp_coupon = {
id: coupon.code,
duration: coupon.validity_per_user
}
if coupon.type == 'percent_off'
stp_coupon[:percent_off] = coupon.percent_off
elsif coupon.type == 'amount_off'
stp_coupon[:amount_off] = coupon.amount_off
stp_coupon[:currency] = Setting.get('stripe_currency')
end
stp_coupon[:redeem_by] = coupon.valid_until.to_i unless coupon.valid_until.nil?
stp_coupon[:max_redemptions] = coupon.max_usages unless coupon.max_usages.nil?
Stripe::Coupon.create(stp_coupon, api_key: Setting.get('stripe_secret_key'))
end
def delete_stripe_coupon(coupon_code)
cpn = Stripe::Coupon.retrieve(coupon_code, api_key: Setting.get('stripe_secret_key'))
cpn.delete
rescue Stripe::InvalidRequestError => e
STDERR.puts "WARNING: Unable to delete the coupon on Stripe: #{e}"
end
def create_or_update_stp_product(class_name, id)
@ -66,5 +49,19 @@ class StripeWorker
object.update_attributes(stp_product_id: product.id)
puts "Stripe product was created for the #{class_name} \##{id}"
end
rescue Stripe::InvalidRequestError
STDERR.puts "WARNING: saved stp_product_id (#{object.stp_product_id}) does not match on Stripe, recreating..."
product = Stripe::Product.create(
{
name: object.name,
metadata: {
id: object.id,
type: class_name
}
}, { api_key: Setting.get('stripe_secret_key') }
)
object.update_attributes(stp_product_id: product.id)
puts "Stripe product was created for the #{class_name} \##{id}"
end
end

View File

@ -42,11 +42,6 @@ module Fablab
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
#
# /!\ ALL locales SHOULD be configured accordingly with this locale. /!\
#
config.i18n.default_locale = Rails.application.secrets.rails_locale
config.i18n.fallbacks = [Rails.application.secrets.app_locale, :en]
config.to_prepare do
Devise::Mailer.layout 'notifications_mailer'

View File

@ -5,3 +5,10 @@ I18n.config.available_locales += %i[en en-AU-CA en-GB en-IE en-IN en-NZ en-US en
es-AR es-CL es-CO es-CR es-DO es-EC es-ES es-MX es-PA es-PE es-US es-VE pt pt-BR zu]
# we allow the Zulu locale (zu) as it is used for In-Context translation
# @see https://support.crowdin.com/in-context-localization/
#
# /!\ ALL locales SHOULD be configured accordingly with the default_locale. /!\
#
I18n.config.default_locale = Rails.application.secrets.rails_locale
I18n.config.locale = Rails.application.secrets.rails_locale

View File

@ -0,0 +1,1441 @@
de:
app:
admin:
#add a new machine
machines_new:
declare_a_new_machine: "Neue Maschine angeben"
watch_out_when_creating_a_new_machine_its_prices_are_initialized_at_0_for_all_subscriptions: "Achtung! Beim Erstellen einer neuen Maschine werden die Preise für alle Abonnements auf 0 initialisiert."
consider_changing_them_before_creating_any_reservation_slot: "Denken Sie daran, sie zu ändern, bevor Sie einen Reservierungsplatz erstellen."
#machine edition
machines_edit:
machine_edit: "Maschine bearbeiten"
#manage the trainings & machines slots
calendar:
calendar_management: "Kalenderverwaltung"
trainings: "Schulungen"
machines: "Maschinen"
spaces: "Räume"
events: "Veranstaltungen"
availabilities: "Verfügbarkeiten"
availabilities_notice: "Export aller für Reservierungen verfügbaren Slots und ihrer Belegung in ein Excel-Arbeitsbuch."
info: "Info"
tags: "Tags"
slot_duration: "Slot-Dauer: {DURATION} Minuten"
ongoing_reservations: "Laufende Reservierungen"
without_reservation: "Ohne Reservierung"
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Wollen Sie wirklich die Reservierung {RESERVATION} von {USER} am {DATE} um {TIME} stornieren?"
reservation_was_successfully_cancelled: "Reservierung wurde erfolgreich storniert."
reservation_cancellation_failed: "Stornierung der Reservierung fehlgeschlagen."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Die letzte Maschine des Slots konnte nicht entfernt werden. Löschen Sie den Slot."
do_you_really_want_to_remove_MACHINE_from_this_slot: "Wollen Sie {MACHINE} wirklich aus diesem Slot entfernen?"
this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing: "Dadurch wird jede neue Reservierung auf diesem Slot verhindert, aber die bestehenden werden nicht storniert."
beware_this_cannot_be_reverted: "Vorsicht: Das kann nicht rückgängig gemacht werden."
the_machine_was_successfully_removed_from_the_slot: "Die Maschine wurde erfolgreich aus dem Slot entfernt."
deletion_failed: "Löschvorgang fehlgeschlagen."
do_you_really_want_to_remove_PLAN_from_this_slot: "Wollen Sie {PLAN} wirklich aus diesem Slot entfernen?"
the_plan_was_successfully_removed_from_the_slot: "Der Plan wurde erfolgreich aus dem Slot entfernt."
DATE_slot: "{DATE} Slot:"
what_kind_of_slot_do_you_want_to_create: "Was für einen Slot wollen Sie erstellen?"
training: "Schulung"
machine: "Maschine"
space: "Raum"
next: "Weiter >"
previous: "< Zurück"
select_some_machines: "Maschinen auswählen"
select_all: "Alle"
select_none: "Keine"
manage_machines: "Klicken Sie hier, um Maschinen hinzuzufügen oder zu entfernen."
manage_spaces: "Klicken Sie hier, um Räume hinzuzufügen oder zu entfernen."
manage_trainings: "Klicke hier, um Schulungen hinzuzufügen oder zu entfernen."
number_of_tickets: "Anzahl der Tickets: "
adjust_the_opening_hours: "Öffnungszeiten anpassen"
to_time: "bis" #eg. from 18:00 to 21:00
restrict_options: "Einschränkungsoptionen"
restrict_with_labels: "Diesen Slot mit Labels einschränken"
restrict_for_subscriptions: "Diesen Slot auf Abonnenten einschränken"
select_some_plans: "Wählen Sie einige Pläne"
plans: "Plan/Pläne:"
recurrence: "Wiederholung"
enabled: "Aktiviert"
period: "Zeitraum"
week: "Woche"
month: "Monat"
number_of_periods: "Anzahl der Zeiträume"
end_date: "Enddatum"
summary: "Zusammenfassung"
select_period: "Bitte wählen Sie einen Zeitraum für die Wiederholung"
select_nb_period: "Bitte wählen Sie eine Anzahl von Zeiträumen für die Wiederholung"
select_end_date: "Bitte wählen Sie das Datum des letzten Ereignisses"
about_to_create: "Sie erstellen nun {TYPE, select, machines{Maschinen} training{Schulungs} space{Raum} other{andere}} {NUMBER, plural, one{Slot} other{Slots}}:"
divided_in_slots: "{COUNT, plural, one {} =1{Dieser Slot wird} other{Diese Slots werden}} für die Buchung in {DURATION}-Minuten-Abschnitten verfügbar sein."
reservable: "Reservierbar(e):"
labels: "Label(s):"
none: "Keine"
slot_successfully_deleted: "Der Slot {START} - {END} wurde erfolgreich gelöscht"
slots_deleted: "Der Slot beginnend mit {START}, und {COUNT, plural, =1{one other} ein weiterer Slot{{COUNT} weitere Slots}}} wurden gelöscht"
unable_to_delete_the_slot: "Konnte den Slot {START} - {END} nicht löschen, wahrscheinlich weil er bereits von einem Mitglied reserviert ist"
slots_not_deleted: "Von {TOTAL} Slots {COUNT, plural, one {} =1{wurde einer wurde nicht gelöscht} other{wurden {COUNT} nicht gelöscht}}. Möglicherweise {COUNT, plural, =1{ist er} other{sind sie}} bereits reserviert."
you_should_select_at_least_a_machine: "Sie sollten mindestens eine Maschine auf diesem Slot auswählen."
export_is_running_you_ll_be_notified_when_its_ready: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt."
actions: "Aktionen"
block_reservations: "Reservierungen blockieren"
do_you_really_want_to_block_this_slot: "Möchten Sie diesen Slot wirklich für neue Reservierungen sperren? Er wird dadurch für Benutzer unsichtbar."
locking_success: "Slot erfolgreich gesperrt. Er wird nicht mehr im Benutzerkalender angezeigt"
locking_failed: "Ein Fehler ist aufgetreten. Sperren des Slots fehlgeschlagen"
allow_reservations: "Reservierungen erlauben"
do_you_really_want_to_allow_reservations: "Wollen Sie wirklich diesen Slot wieder entsperren? Er wird dadurch für die Benutzer wieder sichtbar."
unlocking_success: "Slot erfolgreich entsperrt, er wird wieder im Benutzerkalender angezeigt"
unlocking_failed: "Ein Fehler ist aufgetreten. Entsperren des Slots fehlgeschlagen"
reservations_locked: "Buchung ist gesperrt"
unlockable_because_reservations: "Buchungen auf diesen Slot konnten nicht blockiert werden, da bereits Reservierungen auf ihn gebucht sind."
delete_slot: "Diesen Slot löschen"
do_you_really_want_to_delete_this_slot: "Möchten Sie diesen Slot wirklich löschen?"
delete_recurring_slot: "Sie sind dabei, einen wiederkehrenden Slot zu löschen. Was möchten Sie tun?"
delete_this_slot: "Nur diesen Slot"
delete_this_and_next: "Diesen Slot und die folgenden"
delete_all: "Alle Slots"
event_in_the_past: "In der Vergangenheit kann kein Slot erstellt werden."
edit_event: "Veranstaltung bearbeiten"
view_reservations: "Reservierungen anzeigen"
legend: "Legende"
and: "und"
external_sync: "Kalendersynchronisierung"
divide_this_availability: "Diese Verfügbarkeit teilen in"
slots: "Slots"
slots_of: "von"
minutes: "Minuten"
#import external iCal calendar
icalendar:
icalendar_import: "iCalendar Import"
intro: "Fab-manager erlaubt das automatische Importieren von Kalenderereignissen im RFC 5545 iCalendar Format aus einer externen URL. Diese URL wird stündlich synchronisiert und die Termine werden im öffentlichen Kalender angezeigt. Sie können auch eine Synchronisation auslösen, indem Sie auf den entsprechenden Button vor jedem Import klicken."
new_import: "Neuer ICS-Import"
color: "Farbe"
text_color: "Textfarbe"
url: "URL"
name: "Name"
example: "Beispiel"
display: "Anzeigen"
hide_text: "Text ausblenden"
hidden: "Ausgeblendet"
shown: "Angezeigt"
create_error: "iCalendar Import konnte nicht erstellt werden. Bitte versuchen Sie es später erneut"
delete_failed: "Der iCalendar Import konnte nicht gelöscht werden. Bitte versuchen Sie es später erneut"
refresh: "Aktualisieren..."
sync_failed: "Die URL konnte nicht synchronisiert werden. Bitte versuchen Sie es später erneut"
confirmation_required: "Bestätigung erforderlich"
confirm_delete_import: "Möchten Sie diesen iCalendar Import wirklich löschen?"
delete_success: "iCalendar Import erfolgreich gelöscht"
#management of the projects' components & settings
projects:
name: "Name"
projects_settings: "Projekteinstellungen"
materials: "Materialien"
add_a_material: "Materialien hinfügen"
themes: "Themen"
add_a_new_theme: "Neues Thema hinzufügen"
licences: "Lizenzen"
description: "Beschreibung"
add_a_new_licence: "Neue Lizenz hinzufügen"
manage_abuses: "Berichte verwalten"
settings:
title: "Einstellungen"
comments: "Kommentare"
disqus: "Disqus"
disqus_info: "Wenn Sie Ihren Mitgliedern und Besuchern die Möglichkeit geben möchten, Projekte zu kommentieren, können Sie die Disqus-Foren aktivieren, indem Sie den folgenden Parameter setzen. Besuchen Sie die <a href='https://help.disqus.com/customer/portal/articles/466208-what-s-a-shortname-' target='_blank'>Disqus-Website</a> für weitere Informationen."
shortname: "Kurzname"
cad_files: "CAD-Dateien"
validation: "Validierung"
validation_info: "Benutzer können CAD-Dateien (Computer Aided Design) mit der Dokumentation ihrer Projekte hochladen. Sie können festlegen, welche Dateitypen erlaubt sind. Verwenden Sie die Testeingabe unten, um den MIME-Typ einer Datei zu bestimmen."
extensions: "Zulässige Dateiendungen"
new_extension: "Neue Dateiendung"
new_ext_info_html: "<p>Geben Sie eine neue Dateiendung an, um das Hochladen dieser Dateien zu ermöglichen.</p><p>Bitte beachten Sie, dass das Erlauben von Datei-Archiven (zB. ZIP) oder ausführbaren Programmen (z. EXE) zu einem <strong>gefährlichen Sicherheitsproblem</strong> führen kann und in jedem Fall vermieden werden muss.</p>"
mime_types: "Erlaubte MIME-Typen"
new_mime_type: "Neuer MIME-Typ"
new_type_info_html: "<p>Geben Sie einen neuen MIME-Typen an, um das Hochladen dieser Dateien zu ermöglichen.</p><p>Bitte beachten Sie, dass das Erlauben von Datei-Archiven (z.B. application/zip) oder ausführbaren Programmen (z.B. application/exe) zu einem <strong>gefährlichen Sicherheitsproblem</strong> führen kann und in jedem Fall vermieden werden muss.</p>"
test_file: "Datei testen"
set_a_file: "Datei auswählen"
file_is_TYPE: "Der MIME-Typ dieser Datei ist {TYPE}"
projects_sharing: "Projekte teilen"
open_lab_projects: "OpenLab Projekte"
open_lab_info_html: "Aktivieren Sie OpenLab, um Ihre Projekte mit anderen Fab Labs zu teilen und eine Galerie gemeinsamer Projekte anzuzeigen. Bitte senden Sie eine E-Mail an <a href='mailto:contact@fab-manager.com'>contact@fab-manager.com</a>, um kostenlos Ihre Zugangsdaten zu erhalten."
open_lab_app_id: "ID"
open_lab_app_secret: "Geheimnis"
openlab_default_info_html: "In der Projektgalerie können Besucher zwischen zwei Ansichten wechseln: alle gemeinsam geteilten Projekte des OpenLab-Netzwerkes oder nur die in Ihrem FabLab dokumentierten Projekte.<br/>Hier können Sie die standardmäßig angezeigte Ansicht auswählen."
default_to_openlab: "OpenLab standardmäßig anzeigen"
#track and monitor the trainings
trainings:
trainings_monitoring: "Schulungs-Überwachung"
plan_session: "Neue Sitzung planen"
trainings: "Schulungen"
add_a_new_training: "Neue Schulung hinzufügen"
name: "Name"
associated_machines: "Verknüpfte Maschinen"
number_of_tickets: "Anzahl der Tickets"
select_a_training: "Schulung auswählen"
training: "Schulung"
date: "Datum"
year_NUMBER: "Jahr {NUMBER}"
month_of_NAME: "Monat von {NAME}"
NUMBER_reservation: "{NUMBER} {NUMBER, plural, one{Reservierung} other{Reservierungen}}"
none: "Keine"
training_validation: "Schulungs-Validierung"
training_of_the_DATE_TIME_html: "Schulung vom <strong>{DATE} - {TIME}</strong>"
you_can_validate_the_training_of_the_following_members: "Sie können die Schulung der folgenden Mitglieder validieren:"
deleted_user: "Gelöschter Nutzer"
no_reservation: "Keine Reservierung"
validate_the_trainings: "Schulungen validieren"
edition_of_the_description_tooltip: "Bearbeitung des Beschreibungs-Tooltips"
describe_the_training_in_a_few_words: "Beschreiben Sie die Schulung in wenigen Worten."
description_is_limited_to_255_characters: "Die Beschreibung ist auf 255 Zeichen beschränkt."
description_was_successfully_saved: "Beschreibung wurde erfolgreich gespeichert."
training_successfully_deleted: "Schulung erfolgreich gelöscht."
unable_to_delete_the_training_because_some_users_already_booked_it: "Die Schulung konnte nicht gelöscht werden, da sie bereits von einigen Nutzern gebucht wurde."
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_training: "Möchten Sie diese Schulung wirklich löschen?"
status_enabled: "Aktiviert"
status_disabled: "Deaktiviert"
status_all: "Alle"
#create a new training
trainings_new:
add_a_new_training: "Neue Schulung hinzufügen"
beware_when_creating_a_training_its_reservation_prices_are_initialized_to_zero: "Vorsicht bei der Erstellung eines Trainings, die Reservierungspreise stehen auf Null."
dont_forget_to_change_them_before_creating_slots_for_this_training: "Vergesse nicht, sie anzupassen, bevor du das Training aktivierst."
#events tracking and management
events:
events_monitoring: "Ereignisüberwachung"
manage_filters: "Filter verwalten"
fablab_events: "Fablab-Veranstaltungen"
add_an_event: "Veranstaltung hinzufügen"
all_events: "Alle Veranstaltungen"
passed_events: "Vergangene Veranstaltungen"
events_to_come: "Zukünftige Veranstaltungen"
events_to_come_asc: "Zukünftige Veranstaltungen | chronologische Reihenfolge"
on_DATE: "am {DATE}"
from_DATE: "von {DATE}"
from_TIME: "ab {TIME}"
to_date: "bis" #eg: from 01/01 to 01/05
to_time: "bis" #eg. from 18:00 to 21:00
title: "Titel"
dates: "Datum"
booking: "Buchung"
sold_out: "Ausverkauft"
cancelled: "Storniert"
without_reservation: "Ohne Reservierung"
free_admission: "Freier Eintritt"
view_reservations: "Reservierungen anzeigen"
load_the_next_events: "Die nächsten Veranstaltungen laden..."
categories: "Kategorien"
add_a_category: "Kategorie hinzufügen"
name: "Name"
themes: "Thema"
add_a_theme: "Thema hinzufügen"
age_ranges: "Altersklassen"
add_a_range: "Neue Spanne hinzufügen"
do_you_really_want_to_delete_this_ELEMENT: "Wollen Sie {ELEMENT, select, category{die Kategorie} theme{das Thema} age_range{die Altersklasse} other{Element}} wirklich löschen?"
unable_to_delete_ELEMENT_already_in_use_NUMBER_times: "{ELEMENT, select, category{Die Kategorie} theme{Das Thema} age_range{Die Altersklasse} other{Element}} kann nicht gelöscht werden, weil bereits eine Verbindung mit {NUMBER, plural, =0{keinem Ereignis} one{einem Ereignis} other{{NUMBER} Ereignissen}} besteht."
at_least_one_category_is_required: "Mindestens eine Kategorie ist erforderlich."
unable_to_delete_the_last_one: "Letzte Veranstaltung konnte nicht gelöscht werden."
unable_to_delete_an_error_occured: "Löschen fehlgeschlagen: Ein Fehler ist aufgetreten."
manage_prices_categories: "Preiskategorien verwalten"
prices_categories: "Preiskategorien"
add_a_price_category: "Preiskategorie hinzufügen"
usages_count: "Anzahl der Nutzungen"
price_category: "Preiskategorie"
category_name: "Name der Kategorie"
category_name_is_required: "Der Name der Kategorie ist erforderlich."
enter_here_the_conditions_under_which_this_price_is_applicable: "Geben Sie hier die Bedingungen ein, unter denen dieser Preis anwendbar ist"
conditions_are_required: "Bedingungen sind erforderlich."
price_category_successfully_created: "Preiskategorie erfolgreich erstellt."
unable_to_add_the_price_category_check_name_already_used: "Preiskategorie konnte nicht hinzugefügt werden. Überprüfen Sie, ob der Name nicht bereits verwendet wird."
unexpected_error_occurred_please_refresh: "Ein unerwarteter Fehler ist aufgetreten, bitte aktualisieren Sie die Seite."
price_category_successfully_updated: "Preiskategorie erfolgreich aktualisiert."
unable_to_update_the_price_category: "Preiskategorie konnte nicht aktualisiert werden."
unable_to_delete_this_price_category_because_it_is_already_used: "Diese Preiskategorie kann nicht gelöscht werden, da sie bereits verwendet wird."
do_you_really_want_to_delete_this_price_category: "Möchten Sie diese Preiskategorie wirklich löschen?"
price_category_successfully_deleted: "Preiskategorie erfolgreich gelöscht."
price_category_deletion_failed: "Löschen der Preiskategorie fehlgeschlagen."
#add a new event
events_new:
add_an_event: "Veranstaltung hinzufügen"
none: "Keine"
every_days: "Täglich"
every_week: "Wöchentlich"
every_month: "Monatlich"
every_year: "Jährlich"
#edit an existing event
events_edit:
edit_the_event: "Veranstaltung bearbeiten"
confirmation_required: "Bestätigung erforderlich"
edit_recurring_event: "Sie bearbeiten eine wiederkehrende Veranstaltung. Was möchten Sie ändern?"
edit_this_event: "Nur diese Veranstaltung"
edit_this_and_next: "Diese und die nächste Veranstaltung"
edit_all: "Alle Veranstaltungen"
date_wont_change: "Warnung: Sie haben das Veranstaltungsdatum geändert. Diese Änderung wird nicht für die weiteren Termine der wiederkehrenden Veranstaltung übernommen."
event_successfully_updated: "Veranstaltung erfolgreich aktualisiert."
events_updated: "Die Veranstaltung sowie {COUNT, plural, one {} =1{eine weitere} other{{COUNT} weitere}} wurden aktualisiert"
unable_to_update_the_event: "Veranstaltung konnte nicht aktualisiert werden"
events_not_updated: "Von {TOTAL} Veranstaltungen {COUNT, plural, one {} =1{ wurde eine nicht aktualisiert} other{wurden {COUNT} nicht gelöscht}}."
error_deleting_reserved_price: "Der angeforderte Preis konnte nicht gelöscht werden, da er mit einigen Reservierungen verknüpft ist"
other_error: "Beim Aktualisieren der Veranstaltung ist ein unerwarteter Fehler aufgetreten"
#event reservations list
event_reservations:
the_reservations: "Reservierungen:"
user: "Nutzer"
payment_date: "Zahlungsdatum"
full_price_: "Voller Preis:"
reserved_tickets: "Reservierte Tickets"
show_the_event: "Veranstaltung anzeigen"
no_reservations_for_now: "Momentan keine Reservierung."
back_to_monitoring: "Zurück zur Überwachung"
canceled: "Storniert"
#subscriptions, prices, credits and coupons management
pricing:
pricing_management: "Preisverwaltung"
subscriptions: "Abonnements"
trainings: "Schulungen"
list_of_the_subscription_plans: "Liste der Abonnement-Pläne"
disabled_plans_info_html: "<p><strong>Warnung:</strong> die Abonnements sind in dieser Anwendung deaktiviert.</p><p>Sie können Abonnements erstellen, aber sie werden erst mit der Aktivierung des Planungsmoduls im Abschnitt « Anpassen » verfügbar.</p>"
add_a_new_subscription_plan: "Neues Abonnement hinzufügen"
type: "Typ"
partner: "Partner"
standard: "Standard"
name: "Name"
duration: "Dauer"
group: "Gruppe"
prominence: "Hervorhebung"
price: "Preis"
machine_hours: "Maschinen-Slots"
these_prices_match_machine_hours_rates_html: "Die unten aufgeführten Preise entsprechen einer Stunde Maschinengebrauch, <strong>ohne Abonnement</strong>."
prices_calculated_on_hourly_rate_html: "Alle Preise werden automatisch nach dem hier definierten Stundensatz berechnet.<br/><em>Zum Beispiel</em> wird bei einem veranschlagten Stundensatz von {RATE} ein Slot von {DURATION} Minuten (Standard) zum Preis von <strong>{PRICE}</strong> berechnet."
you_can_override: "Sie können diese Dauer für jede Verfügbarkeit überschreiben, die Sie in der Agenda erstellen. Der Preis wird dann entsprechend angepasst."
machines: "Maschinen"
credits: "Gutschriften"
subscription: "Abonnement"
related_trainings: "Zugehörige Schulungen"
add_a_machine_credit: "Guthaben für die Maschine hinzufügen"
machine: "Maschine"
hours: "Slots (Standard {DURATION} Minuten)"
related_subscriptions: "Zugehörige Abonnements"
please_specify_a_number: "Bitte geben Sie eine Zahl an."
none: "Keine" #grammar concordance with training.
an_error_occurred_while_saving_the_number_of_credits: "Beim Speichern der Guthabenmenge ist ein Fehler aufgetreten."
an_error_occurred_while_deleting_credit_with_the_TRAINING: "Beim Löschen des Guthabens mit {TRAINING} ist ein Fehler aufgetreten."
an_error_occurred_unable_to_find_the_credit_to_revoke: "Ein Fehler ist aufgetreten: Das Guthaben konnte nicht gefunden werden."
an_error_occurred_while_creating_credit_with_the_TRAINING: "Beim Erstellen des Guthabens mit {TRAINING} ist ein Fehler aufgetreten."
not_set: "Nicht festgelegt"
error_a_credit_linking_this_machine_with_that_subscription_already_exists: "Fehler: Ein Guthaben, das diese Maschine mit diesem Abonnement verbindet, existiert bereits."
changes_have_been_successfully_saved: "Ihre Änderungen wurden erfolgreich gespeichert."
credit_was_successfully_saved: "Guthaben wurde erfolgreich gespeichert."
error_creating_credit: "Konnte Guthaben nicht erstellen, ein Fehler ist aufgetreten"
do_you_really_want_to_delete_this_subscription_plan: "Möchten Sie diesen Abonnementplan wirklich löschen?"
subscription_plan_was_successfully_deleted: "Abonnementplan wurde erfolgreich gelöscht."
unable_to_delete_the_specified_subscription_an_error_occurred: "Das angegebene Abonnement konnte nicht gelöscht werden, ein Fehler ist aufgetreten."
coupons: "Gutscheine"
list_of_the_coupons: "Liste der Gutscheine"
discount: "Rabatt"
nb_of_usages: "Anzahl von Nutzungen"
status: "Status"
add_a_new_coupon: "Neuen Gutschein hinzufügen"
display_more_coupons: "Die nächsten Gutscheine anzeigen"
disabled: "Deaktiviert"
expired: "Abgelaufen"
sold_out: "Ausverkauft"
active: "Aktiv"
all: "Alle anzeigen"
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_coupon: "Möchten Sie diesen Gutschein wirklich löschen?"
coupon_was_successfully_deleted: "Gutschein wurde erfolgreich gelöscht."
unable_to_delete_the_specified_coupon_already_in_use: "Der angegebene Gutschein konnte nicht gelöscht werden: Er wird bereits bei einigen Rechnungen verwendet."
unable_to_delete_the_specified_coupon_an_unexpected_error_occurred: "Der angegebene Gutschein konnte nicht gelöscht werden: Ein unerwarteter Fehler ist aufgetreten."
send_a_coupon: "Gutschein senden"
coupon: "Gutschein"
usages: "Verwendungen"
unlimited: "Unbegrenzt"
coupon_successfully_sent_to_USER: "Gutschein erfolgreich an {USER} gesendet"
an_error_occurred_unable_to_send_the_coupon: "Ein unerwarteter Fehler hat verhindert, dass der Gutschein gesendet wird."
code: "Code"
enabled: "Aktiviert"
validity_per_user: "Gültigkeit pro Benutzer"
once: "Nur einmal"
forever: "Jede Nutzung"
valid_until: "Gültig bis (inklusive)"
spaces: "Räume"
these_prices_match_space_hours_rates_html: "Die unten aufgeführten Preise entsprechen einer Stunde Raumbelegung <strong>ohne Abonnement</strong>."
add_a_space_credit: "Guthaben für Raum hinzufügen"
space: "Raum"
error_a_credit_linking_this_space_with_that_subscription_already_exists: "Fehler: Ein Guthaben, das diesen Raum mit diesem Abonnement verbindet, existiert bereits."
status_enabled: "Aktiviert"
status_disabled: "Deaktiviert"
status_all: "Alle"
#ajouter un code promotionnel
coupons_new:
add_a_coupon: "Gutschein hinzufügen"
unable_to_create_the_coupon_check_code_already_used: "Der Gutschein konnte nicht erstellt werden. Bitte überprüfen Sie, ob der Code nicht bereits verwendet wird."
#mettre à jour un code promotionnel
coupons_edit:
coupon: "Gutschein:"
unable_to_update_the_coupon_an_error_occurred: "Gutschein konnte nicht aktualisiert werden: Ein Fehler ist aufgetreten."
plans:
#add a subscription plan on the platform
new:
add_a_subscription_plan: "Abonnement hinzufügen"
unable_to_create_the_subscription_please_try_again: "Das Abonnement konnte nicht erstellt werden. Bitte versuchen Sie es erneut."
successfully_created_subscriptions_dont_forget_to_redefine_prices: "Abonnement(s) erfolgreich erstellt. Vergessen Sie nicht, die Preise neu zu definieren."
unable_to_save_this_user_check_that_there_isnt_an_already_a_user_with_the_same_name: "Der Benutzer konnte nicht gespeichert werden. Überprüfen Sie, ob nicht bereits ein Benutzer mit diesem Namen vorhanden ist."
#edit a subscription plan / machine slots prices
edit:
subscription_plan: "Abonnementplan:"
prices: "Preise"
copy_prices_from: "Preise kopieren von"
machines: "Maschinen"
machine: "Maschine"
hourly_rate: "Stundensatz"
spaces: "Räume"
space: "Raum"
unable_to_save_subscription_changes_please_try_again: "Abonnementänderungen konnten nicht gespeichert werden. Bitte versuchen Sie es erneut."
subscription_successfully_changed: "Abonnement erfolgreich geändert."
#list of all invoices & invoicing parameters
invoices:
invoices: "Rechnungen"
accounting_periods: "Abrechnungszeiträume"
invoices_list: "Rechnungsliste"
filter_invoices: "Rechnungen filtern"
operator_: "Betreiber:"
invoice_num_: "Rechnung Nr:"
customer_: "Kunde:"
date_: "Datum:"
invoice_num: "Rechnung Nr"
date: "Datum"
price: "Preis"
customer: "Kunde"
download_the_invoice: "Rechnung herunterladen"
download_the_credit_note: "Gutschrift herunterladen"
credit_note: "Gutschrift"
display_more_invoices: "Weitere Rechnungen anzeigen..."
no_invoices_for_now: "Momentan keine Rechnungen."
invoicing_settings: "Rechnungs-Einstellungen"
warning_invoices_disabled: "Warnung: Rechnungen sind nicht aktiviert. Es werden keine Rechnungen von Fab-Manager generiert. Trotzdem müssen Sie die unten angegebenen Informationen korrekt ausfüllen, insbesondere die Mehrwertsteuer."
change_logo: "Logo ändern"
john_smith: "Max Mustermann"
john_smith_at_example_com: "max.mustermann@example.com"
invoice_reference_: "Rechnungsbezug:"
code_: "Code:"
code_disabled: "Code deaktiviert"
order_num: "Bestellung #:"
invoice_issued_on_DATE_at_TIME: "Rechnung am {DATE} am {TIME} ausgestellt"
object_reservation_of_john_smith_on_DATE_at_TIME: "Betreff: Reservierung von Max Mustermann am {DATE} um {TIME}"
order_summary: "Bestellungsübersicht:"
details: "Details"
amount: "Betrag"
machine_booking-3D_printer: "Maschinen-Buchung - 3D-Drucker"
total_amount: "Gesamtbetrag"
total_including_all_taxes: "Gesamtpreis inkl. Steuern"
VAT_disabled: "MwSt. deaktiviert"
VAT_enabled: "MwSt. aktiviert"
including_VAT: "Inklusive MwSt."
including_total_excluding_taxes: "Gesamtbetrag zzgl. Steuern"
including_amount_payed_on_ordering: "Inklusive bei Bestellung bezahlter Betrag"
settlement_by_debit_card_on_DATE_at_TIME_for_an_amount_of_AMOUNT: "Begleichung mit Debitkarte am {DATE} um {TIME}, über den Betrag von {AMOUNT}"
important_notes: "Wichtige Hinweise"
address_and_legal_information: "Adresse und rechtliche Informationen"
invoice_reference: "Rechnungsbezug"
year: "Jahr"
month: "Monat"
day: "Tag"
num_of_invoice: "Rechnungsnummer"
online_sales: "Online-Verkäufe"
wallet: "Guthabenkonto"
refund: "Erstattung"
model: "Modell"
documentation: "Dokumentation"
2_digits_year: "Jahr (zwei Ziffern, z.B. 75)"
4_digits_year: "Jahr (vier Ziffern, z.B. 1975)"
month_number: "Monatsnummer (z.B. 1)"
2_digits_month_number: "Monatsnummer (zwei Ziffern, z.B. 01)"
3_characters_month_name: "Monatsname (3 Zeichen, z. B. JAN)"
day_in_the_month: "Tag des Monats (z.B. 1)"
2_digits_day_in_the_month: "Tag des Monats (2 Ziffern, z.B. 01)"
n_digits_daily_count_of_invoices: "(n) Ziffern, tägliche Anzahl von Rechnungen (z. B. ddd => 002 : 2. Rechnung des Tages)"
n_digits_monthly_count_of_invoices: "(n) Ziffern, monatliche Anzahl von Rechnungen (z.B. mmmm => 0012 : 12. Rechnung des Monats)"
n_digits_annual_amount_of_invoices: "(n) Ziffern, jährliche Anzahl von Rechnungen (z.B. yyyyy => 000012 : 12. Rechnung des Monats)"
beware_if_the_number_exceed_the_specified_length_it_will_be_truncated_by_the_left: "Achtung: Wenn die Zahl die angegebene Länge überschreitet, wird sie von links abgeschnitten."
n_digits_count_of_orders: "(n) Ziffern, Anzahl der Bestellungen (z.B. nnnn => 0327 : 327. Bestellung)"
n_digits_daily_count_of_orders: "(n) Ziffern, tägliche Anzahl von Bestellungen (z. B. ddd => 002 : 2. Bestellung des Tages)"
n_digits_monthly_count_of_orders: "(n) Ziffern, monatliche Anzahl von Bestellungen (z. B. mmmm => 0012 : 12. Bestellung des Monats)"
n_digits_annual_amount_of_orders: "(n) Ziffern, jährliche Anzahl von Bestellungen (z.B. yyyyy => 00012 : 12. Bestellung des Jahres"
add_a_notice_regarding_the_online_sales_only_if_the_invoice_is_concerned: "Fügen Sie nur dann eine Mitteilung zu den Online-Verkäufen hinzu, wenn die Rechnung betroffen ist."
this_will_never_be_added_when_a_refund_notice_is_present: "Dies wird nie hinzugefügt, wenn eine Rückerstattung vorhanden ist."
eg_XVL_will_add_VL_to_the_invoices_settled_with_stripe: '(z.B. fügt W[/VL] jenen Rechnungen "/VL" hinzu, die mit Stripe bezahlt werden)'
add_a_notice_regarding_refunds_only_if_the_invoice_is_concerned: "Fügen Sie nur dann eine Mitteilung zu Erstattungen hinzu, wenn die Rechnung betroffen ist."
this_will_never_be_added_when_an_online_sales_notice_is_present: "Dies wird nie hinzugefügt, wenn eine Online-Verkaufsmitteilung vorhanden ist."
eg_RA_will_add_A_to_the_refund_invoices: '(z.B. fügt R[/A] den Rückerstattungsrechnungen "/A" hinzu)'
add_a_notice_regarding_the_wallet_only_if_the_invoice_is_concerned: "Fügen Sie eine Mitteilung zum Guthaben nur dann hinzu, wenn die Rechnung betroffen ist."
eg_WPM_will_add_PM_to_the_invoices_settled_with_wallet: '(z.B. fügt W[/PM] jenen Rechnungen "/PM" hinzu, die mit Guthaben bezahlt werden)'
code: "Code"
enable_the_code: "Code aktivieren"
enabled: "Aktiviert"
disabled: "Deaktiviert"
order_number: "Bestellnummer"
elements: "Elemente"
VAT: "Mwst."
enable_VAT: "MwSt. aktivieren"
VAT_rate: "MwSt.-Satz"
VAT_history: "MwSt.-Sätze Historie"
changed_at: "Geändert am"
changed_by: "Von"
deleted_user: "Gelöschter Nutzer"
refund_invoice_successfully_created: "Rückerstattungsrechnung erfolgreich erstellt."
create_a_refund_on_this_invoice: "Erstelle eine Rückerstattung mit dieser Rechnung"
creation_date_for_the_refund: "Erstellungsdatum für die Erstattung"
creation_date_is_required: "Erstellungsdatum ist erforderlich."
refund_mode: "Erstattungsmodus:"
do_you_want_to_disable_the_user_s_subscription: "Möchten Sie das Abonnement des Benutzers deaktivieren:"
elements_to_refund: "Erstattungselemente"
description: "Beschreibung"
description_optional: "Beschreibung (optional):"
will_appear_on_the_refund_invoice: "Wird auf der Rückerstattungsrechnung angezeigt."
none: "Keine" #grammar concordance with payment mean
by_cash: "In bar"
by_cheque: "Per Scheck"
by_transfer: "Per Banküberweisung"
by_wallet: "Durch Guthaben"
you_must_select_at_least_one_element_to_create_a_refund: "Sie müssen mindestens ein Element auswählen, um eine Rückerstattung zu erstellen."
unable_to_create_the_refund: "Erstattung kann nicht erstellt werden"
invoice_reference_successfully_saved: "Rechnungsreferenz erfolgreich gespeichert."
an_error_occurred_while_saving_invoice_reference: "Beim Speichern der Rechnungsreferenz ist ein Fehler aufgetreten."
invoicing_code_succesfully_saved: "Rechnungscode erfolgreich gespeichert."
an_error_occurred_while_saving_the_invoicing_code: "Beim Speichern des Rechnungscodes ist ein Fehler aufgetreten."
code_successfully_activated: "Code erfolgreich aktiviert."
code_successfully_disabled: "Code erfolgreich deaktiviert."
an_error_occurred_while_activating_the_invoicing_code: "Beim Aktivieren des Rechnungscodes ist ein Fehler aufgetreten."
order_number_successfully_saved: "Bestellnummer erfolgreich gespeichert."
an_error_occurred_while_saving_the_order_number: "Beim Speichern der Bestellnummer ist ein Fehler aufgetreten."
VAT_rate_successfully_saved: "MwSt.-Satz erfolgreich gespeichert."
an_error_occurred_while_saving_the_VAT_rate: "Beim Speichern des Mehrwertsteuersatzes ist ein Fehler aufgetreten."
VAT_successfully_activated: "MwSt. erfolgreich aktiviert."
VAT_successfully_disabled: "MwSt. erfolgreich deaktiviert."
an_error_occurred_while_activating_the_VAT: "Beim Aktivieren der Mehrwertsteuer ist ein Fehler aufgetreten."
text_successfully_saved: "Text erfolgreich gespeichert."
an_error_occurred_while_saving_the_text: "Beim Speichern des Textes ist ein Fehler aufgetreten."
address_and_legal_information_successfully_saved: "Adresse und rechtliche Informationen erfolgreich gespeichert."
an_error_occurred_while_saving_the_address_and_the_legal_information: "Beim Speichern der Adresse und der rechtlichen Informationen ist ein Fehler aufgetreten."
logo_successfully_saved: "Logo erfolgreich gespeichert."
an_error_occurred_while_saving_the_logo: "Beim Speichern des Logos ist ein Fehler aufgetreten."
filename: "Dateiname"
prefix_info: "Die Rechnungen werden als PDF-Dateien generiert, die mit dem folgenden Präfix benannt sind."
prefix: "Präfix"
prefix_successfully_saved: "Dateipräfix erfolgreich gespeichert"
an_error_occurred_while_saving_the_prefix: "Beim Speichern des Dateipräfix ist ein Fehler aufgetreten"
online_payment: "Online-Bezahlung"
close_accounting_period: "Abrechnungszeitraum schließen"
close_from_date: "Schließen ab"
start_date_is_required: "Startdatum ist erforderlich"
close_until_date: "Schließen bis"
end_date_is_required: "Enddatum ist erforderlich"
previous_closings: "Vorherige Schließungen"
start_date: "Von"
end_date: "Bis"
closed_at: "Geschlossen am"
closed_by: "Von"
period_total: "Zeitraum gesamt"
perpetual_total: "Gesamt"
integrity: "Integritätsprüfung"
confirmation_required: "Bestätigung erforderlich"
confirm_close_START_END: "Wollen Sie wirklich den Abrechnungszeitraum zwischen {START} und {END} schließen? Nachfolgende Änderungen sind nicht mehr möglich."
period_must_match_fiscal_year: "Eine Schließung muss am Ende eines Mindestjahreszeitraums oder pro Geschäftsjahr erfolgen, wenn sie nicht kalenderbasiert ist."
this_may_take_a_while: "Dieser Vorgang wird einige Zeit in Anspruch nehmen."
period_START_END_closed_success: "Der Abrechnungszeitraum von {START} bis {END} wurde erfolgreich geschlossen. Die Archivgenerierung läuft, Sie werden nach Abschluss benachrichtigt."
failed_to_close_period: "Ein Fehler ist aufgetreten, der Abrechnungszeitraum konnte nicht geschlossen werden"
no_periods: "Momentan keine Schließungen"
accounting_codes: "Abrechnungscodes"
accounting_journal_code: "Journalcode"
general_journal_code: "Allgemeiner Journalcode"
accounting_card_client_code: "Kartenkunde Code"
card_client_code: "Rechnungscode für Kunden, die mit Kreditkarte bezahlt haben"
accounting_card_client_label: "Kreditkarten-Kunde Label"
card_client_label: "Konto-Label für Kunden, die mit Kreditkarte bezahlt haben"
accounting_wallet_client_code: "Guthabenkonto-Kunde Code"
wallet_client_code: "Rechnungscode für Kunden, die mit dem Guthabenkonto bezahlen"
accounting_wallet_client_label: "Guthabenkonto-Kunde Label"
wallet_client_label: "Konto-Label für Kunden, die mit dem Guthabenkonto bezahlen"
accounting_other_client_code: "Code für anders bezahlende Kunden"
other_client_code: "Rechnungscode für Kunden, die mit einer anderen Zahlungsart bezahlen"
accounting_other_client_label: "Label für anders bezahlende Kunden"
other_client_label: "Rechnungs-Label für Kunden, die mit einer anderen Zahlungsart bezahlen"
accounting_wallet_code: "Guthabenkonto-Code"
general_wallet_code: "Rechnungscode für Guthabenkonto"
accounting_wallet_label: "Guthabenkonto-Label"
general_wallet_label: "Konten-Code für Guthabenkonto"
accounting_vat_code: "MwSt.-Code"
general_vat_code: "Rechnungscode für MwSt."
accounting_vat_label: "MwSt.-Bezeichnung"
general_vat_label: "MwSt.-Konto-Bezeichnung"
accounting_subscription_code: "Abonnement-Code"
general_subscription_code: "Abrechnungscode für alle Abonnements"
accounting_subscription_label: "Abonnementbezeichung"
general_subscription_label: "Abrechnungscode für alle Abonnements"
accounting_Machine_code: "Maschinencode"
general_machine_code: "Abrechnungscode für alle Maschinen"
accounting_Machine_label: "Maschinenbezeichnug"
general_machine_label: "Abrechnungscode für alle Maschinen"
accounting_Training_code: "Trainings-Code"
general_training_code: "Abrechnungscode für alle Schulungen"
accounting_Training_label: "Schulungsbezeichnung"
general_training_label: "Abrechnungs-Label für alle Schulungen"
accounting_Event_code: "Veranstaltungs-Code"
general_event_code: "Abrechnungscode für alle Veranstaltungen"
accounting_Event_label: "Veranstaltungsbezeichnung"
general_event_label: "Abrechnungs-Label für alle Veranstaltungen"
accounting_Space_code: "Raum-Code"
general_space_code: "Abrechnungscode für alle Räume"
accounting_Space_label: "Raumbezeichnung"
general_space_label: "Abrechnungs-Label für alle Räume"
codes_customization_success: "Anpassung der Abrechnungscodes erfolgreich gespeichert."
unexpected_error_occurred: "Beim Speichern der Codes ist ein unerwarteter Fehler aufgetreten. Bitte versuchen Sie es später erneut."
export_accounting_data: "Abrechnungsdaten exportieren"
export_to: "In die Buchhaltungssoftware exportieren"
export_is_running: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt."
acd: "ACD"
export_form_date: "Exportieren ab"
export_to_date: "Exportieren bis"
format: "Dateiformat"
encoding: "Zeichenkodierung"
separator: "Trennzeichen"
dateFormat: "Datumsformat"
labelMaxLength: "Label (max)"
decimalSeparator: "Dezimaltrennzeichen"
exportInvoicesAtZero: "Rechnungen in Höhe von 0 exportieren"
columns: "Spalten"
exportColumns:
journal_code: "Journalcode"
date: "Eintragsdatum"
account_code: "Code des Kontos"
account_label: "Kontobezeichnung"
piece: "Dokument"
line_label: "Eintragsbezeichnung"
debit_origin: "Ursprungssoll"
credit_origin: "Ursprungsguthaben"
debit_euro: "Soll in Euro"
credit_euro: "Guthaben in Euro"
lettering: "Beschriftung"
payment:
payment_settings: "Bezahlungseinstellungen"
online_payment: "Online-Bezahlung"
online_payment_info_html: "Sie können Mitglieden gestatten, direkt online zu buchen und mit Kreditkarte zu bezahlen. Alternativ können Buchungs- und Zahlungsprozesse auf Administratoren und Manager beschränkt werden."
enable_online_payment: "Online-Bezahlung aktivieren"
stripe_keys: "Stripe-Schlüssel"
stripe_keys_info_html: "<p>Um Online-Zahlungen annehmen zu können, müssen die <a href='https://stripe.com' target='_blank'>Stripe</a> API-Schlüssel konfiguriert sein.</p><p>Holen Sie sie von <a href='https://dashboard.stripe.com/account/apikeys' target='_blank'>Ihrem Dashboard</a>.</p><p>Das Aktualisieren dieser Schlüssel synchronisiert alle Stripe-Nutzer neu. Das kann einige Zeit dauern, Sie erhalten eine Benachrichtigung nach Abschluss.</p>"
public_key: "Öffentlicher Schlüssel"
secret_key: "Geheimer Schlüssel"
error_check_keys: "Fehler: Bitte überprüfen Sie Ihre Stripe-Schlüssel."
stripe_keys_saved: "Stripe-Schlüssel erfolgreich gespeichert."
error_saving_stripe_keys: "Die Stripe-Schlüssel konnten nicht gespeichert werden. Bitte versuchen Sie es später erneut."
edit_keys: "Schlüssel bearbeiten"
currency: "Währung"
currency_info_html: "Bitte geben Sie unten die Währung an, die für Online-Bezahlung verwendet wird. Sie sollten einen ISO-Code mit drei Buchstaben aus der Liste <a href='https://stripe.com/docs/currencies' target='_blank'>Stripe unterstützter Währungen eingeben</a>."
currency_alert_html: "<strong>Warnung</strong>: Die Währung kann nicht mehr geändert werden, nachdem die erste Online-Zahlung eingegangen ist. Bitte nehmen Sie diese Einstellung sorgfältig vor, bevor Sie Fab-Manager für Mitglieder öffnen."
stripe_currency: "Stripe-Währung"
#management of users, labels, groups, and so on
members:
users_management: "Benutzer-Verwaltung"
users: "Benutzer"
members: "Mitglieder"
subscriptions: "Abonnements"
search_for_an_user: "Nach einem Benutzer suchen"
add_a_new_member: "Neues Mitglied hinzufügen"
reservations: "Reservierungen"
surname: "Nachname"
first_name: "Vorname"
email: "E-Mail"
phone: "Telefon"
user_type: "Nutzertyp"
subscription: "Abonnement"
display_more_users: "Weitere Benutzer anzeigen..."
administrators: "Administratoren"
search_for_an_administrator: "Nach einem Administrator suchen"
add_a_new_administrator: "Administrator hinzufügen"
managers: "Manager"
managers_info: "Ein Manager ist ein eingeschränkter Administrator, der die Einstellungen der Anwendung nicht ändern kann. Er kann aber für alle Mitglieder und Manager (inkl. sich selbst) Reservierungen vornehmen sowie Bezahlungen und Erstattungen durchführen."
search_for_a_manager: "Nach einem Manager suchen"
add_a_new_manager: "Neuen Manager hinzufügen"
delete_this_manager: "Möchten Sie diesen Manager wirklich löschen? Dies kann nicht rückgängig gemacht werden."
manager_successfully_deleted: "Manager erfolgreich gelöscht."
unable_to_delete_the_manager: "Manager konnte nicht gelöscht werden."
partners: "Partner"
partners_info: "Ein Partner ist ein besonderer Benutzer, der mit den «Partner»-Plänen assoziiert werden kann. Diese Benutzer können sich nicht verbinden und erhalten nur Benachrichtigungen über Abonnements ihres zugehörigen Plans."
search_for_a_partner: "Nach einem Partner suchen"
add_a_new_partner: "Neuen Partner hinzufügen"
delete_this_partner: "Möchten Sie diesen Partner wirklich löschen? Dies kann nicht rückgängig gemacht werden."
partner_successfully_deleted: "Partner erfolgreich gelöscht."
unable_to_delete_the_partner: "Partner konnte nicht gelöscht werden."
associated_plan: "Zugehöriger Plan"
groups: "Gruppen"
tags: "Stichworte"
authentication: "Authentifizierung"
confirmation_required: "Bestätigung erforderlich"
confirm_delete_member: "Möchten Sie dieses Mitglied wirklich löschen? Dies kann nicht rückgängig gemacht werden."
member_successfully_deleted: "Mitglied erfolgreich gelöscht."
unable_to_delete_the_member: "Mitglied kann nicht gelöscht werden."
do_you_really_want_to_delete_this_administrator_this_cannot_be_undone: "Möchten Sie diesen Administrator wirklich löschen? Dies kann nicht rückgängig gemacht werden."
this_may_take_a_while_please_wait: "Warnung: Dies kann eine Weile dauern, bitte haben Sie Geduld."
administrator_successfully_deleted: "Administrator erfolgreich gelöscht."
unable_to_delete_the_administrator: "Administrator konnte nicht gelöscht werden."
changes_successfully_saved: "Änderungen erfolgreich gespeichert."
an_error_occurred_while_saving_changes: "Beim Speichern der Änderungen ist ein Fehler aufgetreten."
export_is_running_you_ll_be_notified_when_its_ready: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt."
tag_form:
tags: "Tags"
add_a_tag: "Tag hinzufügen"
tag_name: "Tag-Name"
new_tag_successfully_saved: "Neuer Tag erfolgreich gespeichert."
an_error_occurred_while_saving_the_new_tag: "Beim Speichern des neuen Tags ist ein Fehler aufgetreten."
confirmation_required: "Tag löschen?"
confirm_delete_tag_html: "Möchten Sie dieses Tag wirklich löschen?<br>Benutzer und Slots, die diesem Tag zugeordnet sind, werden getrennt.<br><strong>Warnung: Dies kann nicht rückgängig gemacht werden!</strong>"
tag_successfully_deleted: "Tag erfolgreich gelöscht."
an_error_occurred_and_the_tag_deletion_failed: "Ein Fehler ist aufgetreten und der Tag konnte nicht gelöscht werden."
authentication_form:
search_for_an_authentication_provider: "Suche nach einem Authentifizierungsanbieter"
add_a_new_authentication_provider: "Neuen Authentifizierungsanbieter hinzufügen"
name: "Name"
strategy_name: "Name der Strategie"
type: "Typ"
state: "Status"
unknown: "Unbekannt: "
active: "Aktiv"
pending: "Ausstehend"
previous_provider: "Vorheriger Anbieter"
confirmation_required: "Anbieter löschen?"
do_you_really_want_to_delete_the_TYPE_authentication_provider_NAME: "Möchten Sie wirklich den Authentifizierungsanbieter {TYPE} löschen: {NAME}?"
authentication_provider_successfully_deleted: "Authentifizierungsanbieter erfolgreich gelöscht."
an_error_occurred_unable_to_delete_the_specified_provider: "Ein Fehler ist aufgetreten: Der angegebene Anbieter konnte nicht gelöscht werden."
local_database: "Lokale Datenbank"
o_auth2: "OAuth 2.0"
group_form:
add_a_group: "Gruppe hinzufügen"
group_name: "Gruppenname"
disable: "Deaktivieren"
enable: "Aktivieren"
changes_successfully_saved: "Änderungen erfolgreich gespeichert."
an_error_occurred_while_saving_changes: "Beim Speichern der Änderungen ist ein Fehler aufgetreten."
new_group_successfully_saved: "Neue Gruppe erfolgreich gespeichert."
an_error_occurred_when_saving_the_new_group: "Beim Speichern der neuen Gruppe ist ein Fehler aufgetreten."
group_successfully_deleted: "Gruppe erfolgreich gelöscht."
unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it: "Gruppe konnte nicht gelöscht werden, da einige Benutzer und/oder Gruppen noch mit ihr verknüpft sind."
group_successfully_enabled_disabled: "Gruppe erfolgreich {STATUS, select, true{deaktiviert} other{aktiviert}}."
unable_to_enable_disable_group: "Gruppe konnte nicht {STATUS, select, true{deaktiviert} other{aktiviert}} werden."
unable_to_disable_group_with_users: "Die Gruppe konnte nicht deaktiviert werden, da sie noch {USERS} {USERS, plural, one {} =1{aktiven Benutzer} other{aktive Benutzer}} enthält."
status_enabled: "Aktiviert"
status_disabled: "Deaktiviert"
status_all: "Alle"
member_filter_all: "Alle"
member_filter_not_confirmed: "Nicht bestätigt"
member_filter_inactive_for_3_years: "Seit 3 Jahren inaktiv"
#add a member
members_new:
add_a_member: "Mitglied hinzufügen"
user_is_an_organization: "Benutzer ist eine Organisation"
#members bulk import
members_import:
import_members: "Mitglieder importieren"
info: "Sie können eine CSV-Datei hochladen, um neue Mitglieder zu erstellen oder bestehende zu aktualisieren. Ihre Datei muss die unten angegebenen Identifikatoren verwenden, um die Gruppe, die Schulungen und die Tags der Mitglieder festzulegen."
required_fields: "Ihre Datei muss mindestens folgende Informationen enthalten, die für jeden Benutzer erstellt werden: E-Mail, Name, Vorname und Gruppe. Wenn das Passwort leer ist, wird es generiert. Bei Aktualisierungen werden leere Felder so beibehalten, wie sie sind."
about_example: "Bitte nutzen Sie die angegebene Beispieldatei, um eine korrekte CSV-Datei zu generieren. Achten Sie auf die Verwendung des UTF-8-Encodings."
groups: "Gruppen"
group_name: "Gruppenname"
group_identifier: "Zu verwendende Kennung"
trainings: "Schulungen"
training_name: "Schulungsbezeichnung"
training_identifier: "Zu verwendende Kennung"
plans: "Pläne"
plan_name: "Planname"
plan_identifier: "Zu verwendende Kennung"
tags: "Tags"
tag_name: "Tag-Name"
tag_identifier: "Zu verwendende Kennung"
download_example: "Beispieldatei"
select_file: "Datei wählen"
import: "Importieren"
update_field: "Referenzfeld für zu aktualisierende Benutzer"
update_on_id: "ID"
update_on_username: "Benutzername"
update_on_email: "EMailAdresse"
#import results
members_import_result:
import_results: "Import-Ergebnisse"
import_details: "Import # {ID} von {DATE}, initiiert von {USER}"
results: "Ergebnisse"
pending: "Ausstehend..."
status_create: "Neuen Benutzer anlegen"
status_update: "Aktualisiere Benutzer {ID}"
success: "Erfolgreich"
failed: "Fehlgeschlagen"
error_details: "Fehlerdetails:"
#edit a member
members_edit:
change_role: "Rolle ändern"
warning_role_change: "<p><strong>Warnung:</strong> das Ändern einer Benutzerrolle ist nicht harmlos. Aktuell ist es nicht möglich, einem Benutzer wieder eine weniger privilegierte Rolle zuzuzuweisen.</p><ul><li><strong>Mitglieder</strong> können nur für sich selbst reservieren und mit Kreditkarte oder Guthabenkonto bezahlen.</li><li><strong>Manager</strong> können für sich selbst Reservierungen buchen und per Kreditkarte oder Guthabenkonto bezahlen sowie auch für andere Mitglieder und Manager, indem sie beim Checkout die Zahlungen einbuchen.</li><li><strong>Administratoren</strong> können nur Reservierungen für Mitglieder und Manager buchen, indem sie indem sie beim Checkout die Zahlungen einbuchen. Außerdem können sie alle Einstellungen der Anwendung ändern.</li></ul>"
admin: "Administrator"
manager: "Manager"
member: "Mitglied"
role_changed: "Rolle erfolgreich von {OLD} auf {NEW} geändert."
error_while_changing_role: "Beim Ändern der Rolle ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut."
subscription: "Abonnement"
duration: "Dauer:"
expires_at: "Läuft ab am:"
price_: "Preis:"
offer_free_days: "Kostenlose Tage anbieten"
extend_subscription: "Abonnement verlängern"
user_has_no_current_subscription: "Benutzer hat kein aktuelles Abonnement."
subscribe_to_a_plan: "Plan abonnieren"
trainings: "Schulungen"
no_trainings: "Keine Schulungen"
next_trainings: "Nächste Schulungen"
passed_trainings: "Absolvierte Schulungen"
validated_trainings: "Validierte Schulungen"
events: "Veranstaltungen"
next_events: "Nächste Veranstaltungen"
no_upcoming_events: "Keine anstehenden Veranstaltungen"
NUMBER_full_price_tickets_reserved: "{NUMBER, plural, =0{} one{1 Vollpreis-Ticket reserviert} other{{NUMBER} Vollpreis-Tickets reserviert}}"
NUMBER_NAME_tickets_reserved: "{NUMBER, plural, =0{} one{1 {NAME}-Ticket reserviert} other{{NUMBER} {NAME}-Tickets reserviert}}"
passed_events: "Vergangene Veranstaltungen"
no_passed_events: "Keine vergangenen Termine"
invoices: "Rechnungen"
invoice_num: "Rechnung Nr"
date: "Datum"
price: "Preis"
download_the_invoice: "Rechnung herunterladen"
download_the_refund_invoice: "Rückerstattungsrechnung herunterladen"
no_invoices_for_now: "Momentan keine Rechnungen."
expiration_date: "Ablaufdatum"
you_intentionally_decide_to_extend_the_user_s_subscription_by_offering_him_free_days: "Sie entscheiden sich absichtlich dafür, das Abonnement des Benutzers zu verlängern, indem Sie ihm kostenlose Tage anbieten."
credits_will_remain_unchanged: "Der Saldo der freien Gutschriften (Schulungen / Maschinen / Räume) des Nutzers bleibt unverändert."
you_intentionally_decide_to_extend_the_user_s_subscription_by_charging_him_again_for_his_current_subscription: "Sie entscheiden sich absichtlich dafür, das Abonnement des Benutzers zu verlängern, indem Sie ihn für sein aktuelles Abonnement erneut belasten."
credits_will_be_reset: "Das Inklusiv-Guthaben (für Schulungen / Maschinen / Räume) des Benutzers wird zurückgesetzt, nicht genutztes Guthaben geht verloren."
until_expiration_date: "Bis (Ablaufdatum):"
you_successfully_changed_the_expiration_date_of_the_user_s_subscription: "Sie haben das Ablaufdatum des Abonnements erfolgreich geändert"
a_problem_occurred_while_saving_the_date: "Beim Speichern des Datums ist ein Problem aufgetreten."
new_subscription: "Neues Abonnement"
you_are_about_to_purchase_a_subscription_to_NAME: "Sie sind dabei, ein Abonnement für {NAME} zu kaufen."
subscription_successfully_purchased: "Abonnement erfolgreich gekauft."
a_problem_occurred_while_taking_the_subscription: "Bei der Übernahme des Abonnements ist ein Problem aufgetreten"
wallet: "Guthabenkonto"
to_credit: 'Guthaben'
cannot_credit_own_wallet: "Sie können keine Gutschrift auf Ihr eigenes Guthaben einbuchen. Bitten Sie einen anderen Manager oder einen Administrator um die Gutschreibung."
cannot_extend_own_subscription: "Sie können Ihr eigenes Abonnement nicht erweitern. Bitte fragen Sie einen anderen Manager oder einen Administrator."
#add a new administrator to the platform
admins_new:
add_an_administrator: "Administrator hinzufügen"
administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Administrator erfolgreich erstellt. {GENDER, select, female{Sie} other{Er}} erhält {GENDER, select, female{ihre} other{seine}} Verbindungsanweisungen per E-Mail."
failed_to_create_admin: "Administrator konnte nicht erstellt werden:"
man: "Männlich"
woman: "Weiblich"
pseudonym: "Pseudonym"
pseudonym_is_required: "Pseudonym ist erforderlich."
first_name: "Vorname"
first_name_is_required: "Der Vorname ist erforderlich."
surname: "Nachname"
surname_is_required: "Der Nachname ist erforderlich."
email_address: "EMailAdresse"
email_is_required: "Die E-Mail-Adresse ist erforderlich."
birth_date: "Geburtsdatum"
address: "Adresse"
phone_number: "Telefonnummer"
#add a new manager to the platform
manager_new:
add_a_manager: "Manager hinzufügen"
manager_successfully_created: "Manager erfolgreich erstellt. {GENDER, select, female{Sie} other{Er}} erhält {GENDER, select, female{ihre} other{seine}} Verbindungsanweisungen per E-Mail."
failed_to_create_manager: "Konnte den Manager nicht erstellen:"
man: "Männlich"
woman: "Weiblich"
pseudonym: "Pseudonym"
pseudonym_is_required: "Pseudonym ist erforderlich."
first_name: "Vorname"
first_name_is_required: "Der Vorname ist erforderlich."
surname: "Nachname"
surname_is_required: "Der Nachname ist erforderlich."
email_address: "EMailAdresse"
email_is_required: "Die E-Mail-Adresse ist erforderlich."
birth_date: "Geburtsdatum"
address: "Adresse"
phone_number: "Telefonnummer"
#add a new authentication provider (SSO)
authentication_new:
local_database: "Lokale Datenbank"
o_auth2: "OAuth 2.0"
add_a_new_authentication_provider: "Neuen Authentifizierungsanbieter hinzufügen"
a_local_database_provider_already_exists_unable_to_create_another: "Ein \"Lokale Datenbank\" Provider existiert bereits. Kann keinen anderen erstellen."
local_provider_successfully_saved: "Lokaler Anbieter erfolgreich gespeichert."
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "Um diesen Provider hinzuzufügen, muss die Übereinstimmung zwischen User.uid und der API festgelegt werden."
security_issue_detected: "Sicherheitsproblem erkannt"
beware_the_oauth2_authenticatoin_provider_you_are_about_to_add_isnt_using_HTTPS: "Vorsicht: Der OAuth 2 Provider, den Sie hinzufügen werden, verwendet kein HTTPS."
this_is_a_serious_security_issue_on_internet_and_should_never_be_used_except_for_testing_purposes: "Dies ist ein ernstes Sicherheitsproblem im Internet und sollte nur für Testzwecke verwendet werden."
do_you_really_want_to_continue: "Möchten Sie wirklich fortfahren?"
unsecured_oauth2_provider_successfully_added: "Ungesicherter OAuth 2.0 Provider erfolgreich hinzugefügt."
oauth2_provider_successfully_added: "OAuth 2.0 Provider erfolgreich hinzugefügt."
#edit an authentication provider (SSO)
authentication_edit:
provider: "Provider:"
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "Um diesen Provider hinzuzufügen, muss die Übereinstimmung zwischen User.uid und der API festgelegt werden."
provider_successfully_updated: "Anbieter erfolgreich aktualisiert."
an_error_occurred_unable_to_update_the_provider: "Ein Fehler ist aufgetreten: Der Anbieter konnte nicht aktualisiert werden."
#statistics tables
statistics:
statistics: "Statistiken"
evolution: "Entwicklung"
age_filter: "Altersfilter"
from_age: "Von" #eg. from 8 to 40 years old
to_age: "bis" #eg. from 8 to 40 years old
start: "Start:"
end: "Ende:"
custom_filter: "Benutzerderfinierter Filter"
NO_: "NO"
criterion: "Kriterium:"
value: "Wert:"
exclude: "Ausschließen"
from_date: "Von" #eg: from 01/01 to 01/05
to_date: "bis" #eg: from 01/01 to 01/05
entries: "Einträge:"
revenue_: "Umsatz:"
average_age: "Durchschnittsalter:"
years_old: "Jahre alt"
total: "Gesamt"
available_hours: "Öffnungszeiten für Buchung:"
available_tickets: "Verfügbare Tickets zur Buchung:"
date: "Datum"
user: "Nutzer"
gender: "Geschlecht"
age: "Alter"
type: "Typ"
revenue: "Umsatz"
unknown: "Unbekannt"
user_id: "Nutzer-ID"
display_more_results: "Weitere Ergebnisse anzeigen"
export_statistics_to_excel: "Statistiken nach Excel exportieren"
export_all_statistics: "Alle Statistiken exportieren"
export_the_current_search_results: "Aktuelle Suchergebnisse exportieren"
export: "Export"
deleted_user: "Gelöschter Nutzer"
man: "Männlich"
woman: "Weiblich"
export_is_running_you_ll_be_notified_when_its_ready: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt."
create_plans_to_start: "Beginnen Sie mit dem Erstellen neuer Abonnement-Pläne."
click_here: "Klicken Sie hier, um die erste zu erstellen."
#statistics graphs
stats_graphs:
statistics: "Statistiken"
data: "Daten"
day: "Tag"
week: "Woche"
from_date: "Ab" #eg: from 01/01 to 01/05
to_date: "bis" #eg: from 01/01 to 01/05
month: "Monat"
start: "Start:"
end: "Ende:"
type: "Typ"
revenue: "Umsatz"
top_list_of: "Top-Liste von"
number: "Zahl"
week_short: "Woche"
week_of_START_to_END: "Woche von {START} bis {END}"
no_data_for_this_period: "Keine Daten in diesem Zeitraum"
date: "Datum"
#global application parameters and customization
settings:
customize_the_application: "Anwendung anpassen"
fablab_name: "FabLab-Name"
about: "Über"
customize_information_messages: "Anpassung der Erklärungstexte"
message_of_the_machine_booking_page: "Erklärungstext der Maschinen-Buchungsseite:"
type_the_message_content: "Inhalt des Erklärungstexts eingeben"
warning_message_of_the_training_booking_page: "Warnmeldung auf der Schulungs-Buchungsseite:"
information_message_of_the_training_reservation_page: "Erklärungstext auf der Seite für die Schulungs-Reservierung:"
message_of_the_subscriptions_page: "Erklärungstext der Abonnement-Seite:"
message_of_the_events_page: "Erklärungstext der Veranstaltungs-Seite:"
message_of_the_spaces_page: "Erklärungstext der Räume-Seite:"
legal_documents: "Rechtliche Dokumente"
if_these_documents_are_not_filled_no_consent_about_them_will_be_asked_to_the_user: "Werden diese Dokumente nicht ausgefüllt, wird keine Zustimmung erbeten."
general_terms_and_conditions: "Allgemeine Geschäftsbedingungen (AGB)"
terms_of_service: "Nutzungsbedingungen"
customize_the_graphics: "Grafiken anpassen"
for_an_optimal_rendering_the_logo_image_must_be_at_the_PNG_format_with_a_transparent_background_and_with_an_aspect_ratio_3.5_times_wider_than_the_height: "Für eine optimale Darstellung muss das Logobild im PNG-Format mit transparenten Hintergrund vorliegen, Seitenverhältnis 3.5 mal breiter als die Höhe."
concerning_the_favicon_it_must_be_at_ICO_format_with_a_size_of_16x16_pixels: "Das Favicon muss im ICO-Format mit einer Größe von 16x16 Pixel vorliegen."
remember_to_refresh_the_page_for_the_changes_to_take_effect: "Die Seite muss neu geladen werden, damit die Änderungen wirksam werden."
logo_white_background: "Logo (weißer Hintergrund)"
change_the_logo: "Logo ändern"
logo_black_background: "Logo (schwarzer Hintergrund)"
favicon: "Favicon"
change_the_favicon: "Favicon ändern"
main_colour: "Hauptfarbe:"
primary: "Primär"
secondary_colour: "Sekundärfarbe:"
secondary: "Sekundär"
background_picture_of_the_profile_banner: "Hintergrundbild des Profil-Banners"
change_the_profile_banner: "Profil-Banner ändern"
home_page: "Homepage"
news_of_the_home_page: "Neuigkeiten der Homepage:"
type_your_news_here: "Gib hier deine News ein"
leave_it_empty_to_not_bring_up_any_news_on_the_home_page: "Lassen Sie es leer, um keine Neuigkeiten auf der Startseite anzuzeigen"
twitter_stream: "Twitter-Stream:"
name_of_the_twitter_account: "Name des Twitter-Kontos"
link: "Link"
link_to_about: 'Link-Titel zur "Über" Seite'
content: "Inhalt"
title_of_the_about_page: "Titel der \"Über\"-Seite"
shift_enter_to_force_carriage_return: "SHIFT + ENTER für Zeilenumbruch"
input_the_main_content: "Hauptinhalt eingeben"
drag_and_drop_to_insert_images: "Ziehen und Ablegen, um Bilder einzufügen"
input_the_fablab_contacts: "FabLab Kontakte eingeben"
reservations: "Reservierungen"
reservations_parameters: "Reservierungsparameter"
confine_the_booking_agenda: "Buchungsagenda festlegen"
opening_time: "Öffnungszeiten"
closing_time: "Schließzeit"
max_visibility: "Maximale Sichtbarkeit (in Monaten)"
visibility_for_yearly_members: "Für derzeit laufende Abonnements, mindestens 1 Jahr lang"
visibility_for_other_members: "Für alle anderen Mitglieder"
ability_for_the_users_to_move_their_reservations: "Möglichkeit für die Benutzer, ihre Reservierungen zu verschieben"
reservations_shifting: "Verschiebung von Reservierungen"
prior_period_hours: "Vorheriger Zeitraum (Stunden)"
enabled: "Aktiviert"
disabled: "Deaktiviert"
ability_for_the_users_to_cancel_their_reservations: "Möglichkeit für Benutzer, ihre Reservierungen zu stornieren"
reservations_cancelling: "Reservierungen stornieren"
reservations_reminders: "Erinnerungen an Reservierungen"
notification_sending_before_the_reservation_occurs: "Senden der Benachrichtigung vor dem Eintreten der Reservierung"
customization_of_SETTING_successfully_saved: "Anpassung von {SETTING} erfolgreich gespeichert."
file_successfully_updated: "Datei erfolgreich aktualisiert."
name_genre: "Titel-Konkordanz"
machine_explications_alert: "Erklärungstext auf der Seite für die Maschinen-Reservierung"
training_explications_alert: "Erklärungstext auf der Seite für die Schulungs-Reservierung"
training_information_message: "Informationstext auf der Seite für die Maschinen-Reservierung"
subscription_explications_alert: "Erklärungstext auf der Seite für die Abonnements"
event_explications_alert: "Erklärungstext auf der Seite für die Veranstaltungs-Reservierung"
space_explications_alert: "Erklärungstext auf der Seite für die Raum-Reservierung"
main_color: "Hauptfarbe"
secondary_color: "Sekundärfarbe"
customize_home_page: "Startseite anpassen"
reset_home_page: "Die Startseite auf den ursprünglichen Zustand zurücksetzen"
confirmation_required: "Bestätigung erforderlich"
confirm_reset_home_page: "Möchten Sie die Startseite wirklich auf ihren Anfangszustand zurücksetzen?"
home_items: "Homepage-Elemente"
item_news: "Neuigkeiten"
item_projects: "Letzte Projekte"
item_twitter: "Letzter Tweet"
item_members: "Neueste Mitglieder"
item_events: "Nächste Veranstaltungen"
home_content: "die Startseite"
home_content_reset: "Die Startseite wurde erfolgreich auf die ursprüngliche Konfiguration zurückgesetzt."
home_css: "das Stylesheet der Startseite"
home_blogpost: "Homepage Kurzinfo"
twitter_name: "Twitter-Benutzername"
link_name: "Link-Titel zur \"Über\" Seite"
about_title: "Seitentitel \"Über\""
about_body: "Seiteninhalt \"Über\""
about_contacts: "Kontakte auf der \"Über\"-Seite"
privacy_draft: "Entwurf der Datenschutzrichtlinien"
privacy_body: "Datenschutzrichtlinie"
privacy_dpo: "Adresse des Datenschutzbeauftragten"
booking_window_start: "Öffnungszeit Beginn"
booking_window_end: "Öffnungszeit Ende"
booking_move_enable: "Verschieben von Reservierungen aktivieren"
booking_move_delay: "vorbeugende Verzögerung der Verschiebung"
booking_cancel_enable: "Buchungsstornierung aktivieren"
booking_cancel_delay: "vorbeugende Verzögerung der Stornierung"
reminder_enable: "Reservierungs-Erinnerung aktivieren"
reminder_delay: "Verzögerung vor dem Versand der Erinnerung"
default_value_is_24_hours: "Wenn das Feld leer bleibt: 24 Stunden."
visibility_yearly: "maximale Sichtbarkeit für jährliche Abonnenten"
visibility_others: "maximale Sichtbarkeit für andere Mitglieder"
display: "Anzeige"
display_name_info_html: "Bei Aktivierung sehen Mitglieder und Besucher im Kalender oder bei der Maschinenbuchung die Namen der Mitglieder, die Slots gebucht haben. Bei Deaktivierung sehen nur Administratoren und Manager die Namen.<br/><strong>Warnung:</strong> wenn Sie dieses Feature aktivieren, müssen sie in Ihren Datenschutzrichtlinien darauf hinweisen."
display_machine_reservation_user_name: "Den vollständigen Namen des Benutzers anzeigen, der einen Maschinenslot gebucht hat"
display_name: "Namen anzeigen"
display_name_enable: "Name anzeigen"
events_in_the_calendar: "Veranstaltungen im Kalender anzeigen"
events_in_calendar_info: "Bei Aktivierung zeigt der Admin-Kalender geplante Veranstaltungen schreibgeschützt an."
show_event: "Veranstaltungen anzeigen"
events_in_calendar: "Veranstaltungsanzeige im Kalender"
machines_sort_by: "Anzeigereihenfolge der Maschinen"
fab_analytics: "Fab-Analytics"
phone_required: "Telefonummer erforderlich"
tracking_id: "Tracking-ID"
facebook_app_id: "Facebook App-ID"
twitter_analytics: "Twitter Analytics-Konto"
book_overlapping_slots: "überlappende Slots buchen"
slot_duration: "Dauer der Slots"
advanced: "Erweiterte Einstellungen"
customize_home_page_css: "Das Stylesheet der Startseite anpassen"
home_css_notice_html: "Sie können das Stylesheet anpassen, das auf die Startseite angewendet wird, indem Sie die <a href=\"https://sass-lang.com/documentation\" target=\"_blank\">SASS</a> Syntax verwenden. Diese Stile werden automatisch dem <code>Homepage</code> Selektor untergeordnet, um das Risiko von Applikationsfehlern zu minimieren. Vorsicht: Änderungen im Homepage-Editor oben auf der Seite können Ihre Stile zerstören, beziehen Sie sich immer auf den HTML-Code."
error_SETTING_locked: "Die Einstellung konnte nicht aktualisiert werden: {SETTING} ist gesperrt. Bitte kontaktieren Sie Ihren Systemadministrator."
an_error_occurred_saving_the_setting: "Beim Speichern der Einstellung ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut."
book_overlapping_slots_info: "Erlauben / Verhindern der Reservierung von überlappenden Slots"
allow_booking: "Buchungen erlauben"
default_slot_duration: "Standarddauer für Slots"
duration_minutes: "Dauer (in Minuten)"
default_slot_duration_info: "Die Verfügbarkeit von Maschinen und Räumen ist in mehrere Slots dieser Dauer aufgeteilt. Dieser Wert kann je Verfügbarkeit überschrieben werden."
modules: "Module"
spaces: "Räume"
spaces_info_html: "<p>Ein Raum kann zum Beispiel eine Holzwerkstatt oder ein Meetingraum sein. Die Besonderheit von Räumen ist, dass sie von mehreren Personen gleichzeitig gebucht werden können.</p><p><strong>Warnung:</strong> Es wird nicht empfohlen, Räume zu deaktivieren, wenn mindestens eine Raumreservierung auf dem System vorgenommen wurde.</p>"
enable_spaces: "Räume aktivieren"
spaces_module: "Raum-Modul"
plans: "Pläne"
plans_info_html: "<p>Abonnements bieten eine Möglichkeit, Ihre Preise zu segmentieren und Vorteile für reguläre Benutzer zu bieten.</p><p><strong>Warnung:</strong> Es wird nicht empfohlen, die Abonnements zu deaktivieren, wenn mindestens ein Abonnement auf dem System aktiv ist.</p>"
enable_plans: "Pläne aktivieren"
plans_module: "Plan-Modul"
invoicing: "Rechnungsstellung"
invoicing_info_html: "<p>Sie können das Rechnungsmodul komplett deaktivieren.</p><p>Das ist nützlich, wenn Sie über Ihr eigenes Rechnungssystem verfügen und nicht wollen, dass Fab-Manager Rechnungen generiert und an Mitglieder sendet.</p><p><strong>Warnung:</strong> Auch wenn Sie das Rechnungsmodul deaktivieren, müssen Sie die Mehrwertsteuer konfigurieren, um Fehler in Rechnungslegung und Preisen zu vermeiden. Die Konfiguration erfolgt in der Sektion « Rechnungen > Einstellungen ».</p>"
enable_invoicing: "Rechnungsstellung aktivieren"
invoicing_module: "Rechnungs-Modul"
account_creation: "Account-Erstellung"
phone: "Telefon"
phone_is_required: "Telefonummer erforderlich"
phone_required_info: "Sie können festlegen, ob die Telefonnummer erforderlich sein soll, um einen neuen Benutzer auf Fab-Manager zu registrieren."
captcha: "Captcha"
captcha_info_html: "Sie können einen Schutz gegen Roboter einrichten, um zu verhindern, dass diese Accounts erstellen. Dieser Schutz verwendet Google reCAPTCHA. Melden Sie sich für <a href='http://www.google.com/recaptcha/admin' target='_blank'>ein API-Schlüsselpaar</a> an, um reCaptcha zu verwenden."
site_key: "Site-Schlüssel"
secret_key: "Geheimer Schlüssel"
recaptcha_site_key: "ReCAPTCHA Site-Key"
recaptcha_secret_key: "reCAPTCHA Geheimschlüssel"
feature_tour_display: "Anzeige der Tour zu den Features"
email_from: "Mailadresse des Senders"
disqus_shortname: "Disqus Kurzname"
COUNT_items_removed: "{COUNT, plural, one {} =1{Ein Element} other{{COUNT} Elemente}} entfernt"
item_added: "Ein Element hinzugefügt"
openlab_app_id: "OpenLab-ID"
openlab_app_secret: "OpenLab App-Geheimnis"
openlab_default: "Standard-Galerieansicht"
online_payment_module: "Online-Zahlungsmodul"
stripe_currency: "Stripe-Währung"
account_confirmation: "Kontobestätigung"
confirmation_required_info: "Optional können Sie die Bestätigung der E-Mail-Adresse für Benutzer obligatorisch machen, bevor Sie Zugriff auf Fab-Manager bekommen."
confirmation_is_required: "Bestätigung erforderlich"
wallet_module: "Guthabenkonto-Modul"
statistics_module: "Statistik-Modul"
upcoming_events_shown: "Anzeigelimit für anstehende Termine"
general:
general: "Allgemein"
title: "Titel"
fablab_title: "FabLab Titel"
title_concordance: "Titel-Konkordanz"
male: "Männlich."
female: "Weiblich."
neutral: "Neutral."
eg: "z.B.:"
the_team: "Das Team von"
male_preposition: "der"
female_preposition: "die"
neutral_preposition: ""
elements_ordering: "Elemente sortieren"
machines_order: "Maschinen-Reihenfolge"
display_machines_sorted_by: "Maschinen anzeigen, sortiert nach"
sort_by:
default: "Standard"
name: "Name"
created_at: "Erstellungsdatum"
updated_at: "Datum der letzten Aktualisierung"
help: "Hilfe"
feature_tour: "Feature-Tour"
feature_tour_info_html: "<p>Wenn sich ein Administrator oder Manager anmeldet, wird beim jeweils ersten Besuch eines Abschnitts der Anwendung die Feature-Tour ausgelöst. Sie können dieses Verhalten auf einen der folgenden Werte ändern:</p><ul><li>« Einmal », um das Standardverhalten beizubehalten.</li><li>« Pro Sitzung », um die Tour jedes Mal anzuzeigen, wenn die Anwendung erneut geöffnet wird.</li><li>« Nur manuell », deaktiviert die automatische Anzeige der Touren. Es ist weiterhin möglich, sie durch Drücken der F1-Taste oder durch Klicken auf « Hilfe » im Benutzermenu zu starten.</li></ul>"
feature_tour_display_mode: "Anzeigemodus der Feature Tour"
display_mode:
once: "Einmalig"
session: "Pro Sitzung"
manual: "Manuell"
notifications: "Mitteilungen"
email: "E-Mail"
email_info: "Die E-Mail-Adresse, von der Benachrichtigungen gesendet werden. Sie können eine nicht vorhandene Adresse (wie noreply@...) verwenden oder eine bestehende Adresse, wenn Sie Ihren Mitgliedern erlauben möchten, auf Benachrichtigungen zu antworten."
email_from: "Mailadresse des Senders"
wallet: "Guthabenkonto"
wallet_info_html: "<p>Mit dem Guthabenkonto können Sie Benutzern eine Geldsumme zuweisen. Diese können es nach Belieben im Fab-Manager ausgeben.</p><p>Mitglieder können ihr Guthabenkonto nicht selbst aufladen, das können nur Manager und Administratoren.</p>"
enable_wallet: "Guthabenkonto aktivieren"
statistics: "Statistiken"
statistics_info_html: "<p>Aktivieren oder deaktivieren Sie das Statistik-Modul.</p><p>Wenn aktiviert, konsolidiert das Modul die Tagesdaten in der Datenbank einer leistungsstarken Analyse-Engine. Administratoren können im entsprechenden Abschnitt die erstellten Diagramme und Tabellen durchsuchen.</p>"
enable_statistics: "Statistik-Modul aktivieren"
home:
show_upcoming_events: "Anstehende Veranstaltungen anzeigen"
upcoming_events:
until_start: "Bis sie beginnen"
2h_before_end: "Bis 2 Stunden vor ihrem Ende"
until_end: "Bis sie enden"
privacy:
title: "Datenschutz"
privacy_policy: "Datenschutzerklärung"
input_the_dpo: "Datenschutzbeauftragter"
current_policy: "Aktuelle Richtlinie"
draft_from_USER_DATE: "Entwurf gespeichert von {USER} am {DATE}"
save_or_publish: "Speichern oder veröffentlichen?"
save_or_publish_body: "Möchten Sie eine neue Version der Datenschutzrichtlinie veröffentlichen oder sie als Entwurf speichern?"
publish_will_notify: "Veröffentlichen der neuen Version sendet eine Benachrichtigung an alle Benutzer."
publish: "Veröffentlichen"
users_notified: "Plattform-Nutzer werden über das Update benachrichtigt."
about_analytics: "Ich stimme zu, anonyme Daten mit dem Entwicklerteam zu teilen, um Fab-Manager zu verbessern."
read_more: "Welche Daten werden von uns erfasst?"
statistics: "Statistiken"
google_analytics: "Google Analytics"
facebook: "Facebook"
facebook_info_html: "Um die statistische Verfolgung der Aktien im sozialen Netzwerk Facebook zu aktivieren, legen Sie hier Ihre App-ID fest. <a href='https://developers.facebook.com/docs/apps#register' target='_blank'>Diese Anleitung</a> erklärt, wie Sie eine App-ID erhalten."
app_id: "App-ID"
twitter: "Twitter"
twitter_info_html: "Um Statistiken im sozialen Netzwerk Twitter via <a href='https://analytics.twitter.com/' target='_blank'>Twitter Analytics</a> zu aktivieren, können Sie hier den Namen Ihres Twitter-Kontos eingeben."
twitter_analytics: "Twitter-Konto"
analytics:
title: "Anwendungsverbesserung"
intro_analytics_html: "Sie finden unten eine detaillierte Ansicht der Daten, die Fab-Manager sammelt, <strong>wenn die Erlaubnis erteilt wurde.</strong>"
version: "Anwendungsversion"
members: "Mitgliederanzahl"
admins: "Anzahl der Administratoren"
availabilities: "Anzahl der Verfügbarkeiten der letzten 7 Tage"
reservations: "Anzahl der Reservierungen in den letzten 7 Tagen"
plans: "Ist das Abonnement-Modul aktiv?"
spaces: "Ist das Raum-Management-Modul aktiv?"
online_payment: "Ist das Online-Zahlungsmodul aktiv?"
invoices: "Ist das Rechnungsmodul aktiv?"
openlab: "Ist das Projektteilungsmodul (OpenLab) aktiv?"
tracking_id_info_html: "<p>Um die statistische Analyse der Besuche mithilfe von Google Analytics zu ermöglichen, tragen Sie hier Ihre Tracking-ID in der Form UA-000000-0 ein. Besuchen Sie <a href='https://analytics.google.com/analytics/web/' target='_blank'>die Google Analytics Website</a>, um eine Tracking-ID zu erstellen.<br/><strong>Warnung:</strong> wenn Sie dieses Feature aktivieren, muss in Ihrer Datenschutzrichtlinie darauf hingewiesen werden.</p><p> Um Google Analytics verwenden zu können, benötigen Sie auch den Hostnamen. Klicken Sie auf die angrenzende Schaltfläche. Dieser letzte Parameter wird auch an anderen Stellen verwendet, bitte verwenden Sie ihn vorsichtig.</p>"
tracking_id: "Tracking-ID"
open_api_clients:
add_new_client: "Neuen API-Client erstellen"
api_documentation: "API-Dokumentation"
open_api_clients: "OpenAPI-Clients"
name: "Name"
calls_count: "Anrufanzahl"
token: "Token"
created_at: "Erstellungsdatum"
reset_token: "Zugriff widerrufen"
client_name: "Kundenname"
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_open_api_client: "Möchten Sie diesen OpenAPI-Client wirklich löschen?"
do_you_really_want_to_revoke_this_open_api_access: "Möchten Sie diesen Zugriff wirklich widerrufen ? Er wird das aktuelle Token löschen und ersetzen."
client_successfully_created: "Client erfolgreich erstellt."
client_successfully_updated: "Client erfolgreich aktualisiert."
client_successfully_deleted: "Client erfolgreich gelöscht."
access_successfully_revoked: "Zugriff erfolgreich widerrufen."
#create a new space
space_new:
add_a_new_space: "Neuen Raum erstellen"
watch_out_when_creating_a_new_space_its_prices_are_initialized_at_0_for_all_subscriptions: "Achtung! Beim Erstellen eines neuen Raums wird sein Preis für alle Abonnements mit 0 angelegt."
consider_changing_its_prices_before_creating_any_reservation_slot: "Ändern Sie ggf. die Preise, bevor Sie Reservierungs-Slots erstellen."
add_this_space: "Diesen Raum hinzufügen"
#modify an exiting space
space_edit:
edit_the_space_NAME: "Bearbeite den Raum: {NAME}"
validate_the_changes: "Änderungen validieren"
#process and delete abuses reports
manage_abuses:
abuses_list: "Berichtsliste"
no_reports: "Momentan keine Berichte"
published_by: "verfasst von"
at_date: "am"
has_reported: "hat folgenden Bericht erstellt:"
confirmation_required: "Bestätigen Sie die Bearbeitung des Berichts"
report_will_be_destroyed: "Sobald der Bericht verarbeitet wurde, wird er gelöscht. Dies kann nicht rückgängig gemacht werden. Fortfahren?"
report_removed: "Der Bericht wurde gelöscht"
failed_to_remove: "Ein Fehler ist aufgetreten, der Bericht konnte nicht gelöscht werden"
#feature tour
tour:
conclusion:
title: "Vielen Dank für Ihre Aufmerksamkeit"
content: "<p>Um diese kontextabhängige Hilfe neu zu starten, können Sie jederzeit <strong>F1</strong> drücken oder klicken Sie im Benutzermenu auf [? Hilfe].</p><p>Zusätzliche Hilfe finden Sie in der <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.5.pdf' target='_blank'>Benutzeranleitung</a> (nur auf Französisch).</p><p>Das Fab-Manager-Team bietet auch personalisierten Support (Hilfe beim Einstieg, Hilfe bei der Installation, Anpassung etc.), <a href='mailto:contact@fab-manager.com'>kontaktieren Sie uns</a> für weitere Informationen.</p>"
trainings:
welcome:
title: "Schulungen"
content: "Hier können Sie Schuluigen erstellen, ändern und löschen. Ebenso können Sie hier die Schulungen validieren, die von Mitgliedern absolviert wurden."
welcome_manager:
title: "Schulungen"
content: "Hier sehen Sie die Schulungen und ihre jeweiligen Maschinenzuordnungen. Ebenso können Sie hier Schulungen validieren, die von Mitgliedern absolviert wurden."
trainings:
title: "Schulungen verwalten"
content: "<p>Jeder Schulung ist eine Standardanzahl von Räumen zugeordnet. Die Anzahl der tatsächlichen Räume kann für jede Einzelschulung geändert werden.</p><p>Schulungen werden über den Administrations-Tab « Kalender » geplant.</p><p>Einer Schulung können eine oder mehrere Maschinen zugeordnet werden. Dadurch wird es zur Voraussetzung zur Reservierung dieser Maschinen.</p>"
filter:
title: "Filter"
content: "Standardmäßig werden hier nur aktive Kurse angezeigt. Um andere anzuzeigen, können Sie einen anderen Filter auswählen."
tracking:
title: "Schulungs-Überwachung"
content: "Sobald eine Schulung abgeschlossen ist, kann sie hier für die anwesenden Mitglieder validiert werden. Die Validierung ist unerlässlich, um mit der Schulung assoziierte Maschinen benutzen zu dürfen."
calendar:
welcome:
title: "Kalender"
content: "Hier können die Slots geplant werden, in denen Mitglieder Schulungen, Maschinen und Räume buchen können."
agenda:
title: "Der Kalender"
content: "Klicken Sie in den Kalender, um einen neuen Verfügbarkeits-Zeitraum zu erstellen. Sie können den Zeitraum durch Klicken und Halten direkt auswählen."
export:
title: "Export"
content: "Erstellen Sie eine Excel-Datei, die alle im Kalender erstellten Verfügbarkeits-Slots auflistet."
import:
title: "Externe Kalender importieren"
content: "Erlaubt den Import von Kalendern im iCal-Format aus einer externen Quelle."
members:
welcome:
title: "Nutzer"
content: "Hier können Sie Mitglieder und Administratoren erstellen, ändern und löschen. Sie verwalten hier auch Gruppen, Labels, Import/Export mit Spreadsheets und können SSO-Software anschließen."
list:
title: "Mitgliederliste"
content: "Standardmäßig listet diese Tabelle alle Mitglieder des Fab-Managers auf. Sie können die Listensortierung per Klick auf die verschiedenen Spaltenheader ändern."
search:
title: "Benutzer suchen"
content: "Über dieses Eingabefeld können Sie eine Freitextsuche über alle Spalten der Tabelle unten starten."
filter:
title: "Liste filtern"
content: "<p>Filtern Sie die Liste unten, um nur Benutzer mit unbestätigter E-Mail-Adresse oder mehr als 3 Jahren Inaktivität anzuzeigen.</p><p>Bitte beachten Sie, dass aus Datenschutzgründen Konten gelöscht werden müssen, die länger als 3 Jahre inaktiv sind.</p>"
actions:
title: "Mitglieder-Aktionen"
content: "<p>Mit den Schaltflächen in dieser Spalte können Sie alle Parameter des Mitglieds anzeigen, ändern oder unwiderruflich löschen.</p><p>Im Falle einer Löschung werden die Abrechnungsinformationen noch für 10 Jahre aufbewahrt. Anonymisierte statistische Daten werden ebenfalls erhalten.</p>"
exports:
title: "Export"
content: "Jeder Button generiert ein Excel-Datei, die jeweils alle Mitglieder, Abonnements oder Reservierungen enthält, mit sowohl aktuellen wie historischen Daten."
import:
title: "Mitglieder importieren"
content: "Importiert eine Liste von Mitgliedern aus einer CSV-Datei, die im Fab-Manager angelegt werden."
admins:
title: "Administratoren verwalten"
content: "Administratoren werden hier analog zu den Mitgliedern verwaltet.<br>Administratoren können Reservierungen für jedes Mitglied vornehmen und alle Parameter der Software ändern."
groups:
title: "Gruppen verwalten"
content: "<p>Gruppen ermöglichen die bessere Segmentierung der Preisliste.</p><p>Wenn Sie Fab-Manager zum ersten Mal einrichten, wird der Einstieg mit der Gruppendefinition empfohlen.</p>"
labels:
title: "Tags verwalten"
content: "Mit Labeln können Sie bestimmte Slots für Benutzer reservieren, die diesen Labels zugeordnet sind."
sso:
title: "Single-Sign-On"
content: "Hier können Sie ein Single-Sign-On-Authentifizierungssystem (SSO) einrichten und verwalten."
invoices:
welcome:
title: "Rechnungen"
content: "<p>Hier können Sie Rechnungen und Gutschriften herunterladen, sowie alles rund um Abrechnung und Rechnungsstellung verwalten.</p><p>Wenn Sie Ihre Rechnungen mit einer anderen Software verwalten, kann das Abrechnungsmodul deaktiviert werden. Kontaktieren Sie dazu Ihren Systemadministrator.</p>"
welcome_manager:
title: "Rechnungen"
content: "Hier können Sie Rechnungen herunterladen und Gutschriften erstellen."
list:
title: "Rechnungsliste"
content: "Diese Tabelle listet standardmäßig alle Rechnungen und Kreditnoten von Fab-Manager auf. Sie können die Liste in einer anderen Reihenfolge sortieren, indem Sie auf den Header jeder Spalte klicken."
chained:
title: "Verkettungs-Anzeiger"
content: "<p>Dieses Icon stellt die Unänderbarkeit der Rechnungsdaten der Rechnung in dieser Zeile sicher in Übereinstimmung mit dem französischen Finanzgesetz von 2018 gegen Mehrwertsteuerbetrug.</p><p>Wenn anstelle dieses Symbol ein rotes Symbol erscheint, wenden Sie sich bitte sofort an den technischen Support.</p>"
download:
title: "Herunterladen"
content: "Klicken Sie hier, um die Rechnung im PDF-Format herunterzuladen."
refund:
title: "Gutschrift"
content: "Ermöglicht die Erstellung einer Gutschrift für die Rechnung in dieser Zeile oder für ihre Unterelemente. <strong>Warnung:</strong> Nur das Rechnungsdokument wird generiert, die tatsächliche Gutschrift für den Benutzer wird immer in Ihrer Verantwortung liegen."
settings:
title: "Einstellungen"
content: "<p>Hier können Sie die Parameter für die Rechnungserstellung ändern. Klicken Sie auf das Element, das Sie bearbeiten wollen.</p><p>Insbesondere legen Sie hier fest, ob Sie der Mehrwertsteuer unterliegen und zu welchem Satz.</p>"
codes:
title: "Abrechnungscodes"
content: "Legen Sie hier die Abrechnungscodes für alle Arten von Einträgen fest, die von der Software generiert werden. Diese Einstellung ist nur erforderlich, wenn Sie den Abrechnungsexport verwenden."
export:
title: "Abrechnungsexport"
content: "Sobald die Codes konfiguriert sind, klicken Sie hier, um die Einträge in eine externe Buchhaltungssoftware zu exportieren."
payment:
title: "Zahlungseinstellungen"
content: "Wenn Sie Ihren Mitgliedern die Möglichkeit geben, direkt online per Kreditkartenzahlung zu buchen, wird die Funktion von dieser Seite aus aktiviert und konfiguriert."
periods:
title: "Abrechnungszeiträume schließen"
content: "<p>Die Bestimmungen IhresLandes können es erfordern, dass Sie Konten regelmäßig schließen müssen. Über diese Schaltfläche können Sie auf die Einstellungsmöglichkeiten zugreifen.</p> <p><strong>In Frankreich</strong> ist diese Schließung mindestens einmal im Jahr verpflichtend, wenn Sie dem MwSt.-Antibetrugsgesetz nach <a href='https://bofip.impots.gouv.fr/bofip/10691-PGP.html' target='_blank'>BOI-TVA-DECLA-30-10-30-20160803</a> unterworfen sind.</p><p>Zur Erinnerung: wenn Sie eine zertifizierte Software verwenden müssen (<a href='https://www.impots.gouv.fr/portail/suis-je-oblige-davoir-un-logiciel-de-caisse-securise' target='_blank'>Test hier</a>), sind Sie sind gesetzlich zur Vorlage eines Zertifikats der Einhaltung durch die Software verpflichtet. <a href='mailto:contact@fab-manager.com'>Kontaktieren Sie uns<a/>, um es zu erhalten.</p>"
pricing:
welcome:
title: "Abonnements und Preise"
content: "Verwalten Sie Abonnements und Preise für die Dienste, die Sie Ihren Mitgliedern anbieten."
new_plan:
title: "Neuer Abonnementplan"
content: "Erstellen Sie Abonnementpläne, um regulären Benutzern ermäßigte Preise auf Maschinen und Räume anzubieten."
trainings:
title: "Schulungen"
content: "Definieren Sie Preise der Schulungen nach Benutzergruppe."
machines:
title: "Maschinen"
content: "Legen Sie hier die Preise für die Maschinenslots nach Benutzergruppe fest. Diese Preise gelten für Benutzer ohne Abonnements."
spaces:
title: "Räume"
content: "Ebenso legen Sie hier die Preise der Raum-Slots für Benutzer ohne Abonnements fest."
credits:
title: "Gutschriften"
content: "<p>Über Gutschriften können Benutzer mit Abonnements bestimmte Dienste kostenlos nutzen.</p><p>Sie können beispielsweise 2 Stunden 3D-Drucker für alle Jahresabonnementen anbieten oder eine Schulung Ihrer Wahl für Studierende etc.</p>"
coupons:
title: "Gutscheine"
content: "Erstellen und verwalten Sie Gutscheine, um ihren Inhabern einzelne Rabatte zu bieten."
events:
welcome:
title: "Veranstaltungen"
content: "Hier erstellen und organisieren Sie Veranstaltungen und überwachen den Reservierungsverlauf."
list:
title: "Die Veranstaltungen"
content: "Diese Liste zeigt vergangene oder zukünftige Veranstaltungen sowie die jeweilige Anzahl der Reservierungen."
filter:
title: "Veranstaltungen filtern"
content: "Wahlweise nur zukünftige oder nur vergangene Veranstaltungen in der folgenden Liste anzeigen."
categories:
title: "Kategorien"
content: "Mit Kategorien informieren Sie Ihre Nutzer über die jeweilige Veranstaltungsart. Neu erstellten Veranstaltungen muss eine Kategorie zugewiesen werden."
themes:
title: "Themen"
content: "<p>Themen sind eine zusätzliche (optionale) Kategorisierung von Veranstaltungen. Sie können Veranstaltungen unterschiedlicher Formen gruppieren.</p><p>Ein zweitägiger Kurs zu Einlegearbeiten und ein Abendworkshop zum Umgang mit der Abrichte können z.B. unter dem Thema « Tischlerei » gruppiert werden.</p>"
ages:
title: "Altersgruppen"
content: "Ein (optionaler) Filter, der Nutzern helfen kann, für sie geeignete Veranstaltungen zu finden."
prices:
title: "Preiskategorien"
content: "Der Preis einer Veranstaltung hängt nicht von Gruppen oder Abonnements ab, sondern von den Kategorien, die Sie auf dieser Seite definieren."
projects:
welcome:
title: "Projekte"
content: "Hier können Sie alle Elemente definieren, die Mitgliedern für die Dokumentation ihrer Projekte zur Verfügung stehen. Ebenso können weitere Projekt-Parameter definiert werden."
abuses:
title: "Meldungen verwalten"
content: "<p>Zugriff auf die Meldungsverwaltung.</p><p>Besucher können Projekte melden, beispielsweise wegen Urheberrechtsverletzungen oder Hetze.</p><p>Datenschutzrechtlich sind Sie zur Löschung dieser Meldungen verpflichtet, sobald die erforderlichen Maßnahmen durchgeführt wurden.</p>"
settings:
title: "Einstellungen"
content: "<p>Kommentare, CAD-Dateien ... Verwalten Sie hier Projektparameter.</p><p>Sie können auch die OpenLab-Projekte aktivieren, um von anderen FabLabs geteilte Projekte in Ihrer Galerie anzuzeigen.</p>"
statistics:
welcome:
title: "Statistiken"
content: "<p>Zugriff auf Daten und Statistiken über die Mitglieder und deren Verwendungszwecke im FabLab.</p><p>Gemäß der Datenschutzverordnung werden Benutzer, die ihr Konto gelöscht haben, zwar weiter in den Statistiken aufgeführt, die Daten aber anonymisiert.</p>"
export:
title: "Daten exportieren"
content: "Sie können wahlweise alle oder einen Teil der statistischen Daten in eine Excel-Datei exportieren."
trending:
title: "Entwicklung"
content: "Visualisieren Sie mit Grafiken und Kurven die Entwicklung der FabLab-Nutzung über die Zeit."
settings:
welcome:
title: "Anpassung der Applikation"
content: "Von hier aus konfigurieren Sie allgemeine Einstellungen von Fab-Manager, können optionale Module aktiviert und deaktiviert sowie die Benutzeroberfläche angepasst werden."
general:
title: "Allgemeine Einstellungen"
content: "Viele Einstellungen können von hier aus vorgenommen werden. Nehmen Sie sich für diese Seite Zeit: hier können Nachrichten, Dokumente, optionale Module, Registrierungen, das Erscheinungsbild von Fab-Manager und vieles mehr angepasst werden."
home:
title: "Startseite anpassen"
content: "<p>Mit diesem WYSIWYG-Editor können Sie das Aussehen der Startseite anpassen, indem Sie verschiedene Komponenten verwenden (letzter Tweet, Kurzinformation etc.).</p><p><strong>Warnung:</strong> Beachten Sie, dass unbedachte Änderungen das Aussehen der Startseite beschädigen können.</p>"
components:
title: "Komponente einfügen"
content: "Hier klicken, um eine bestehende Komponente in die Startseite einzufügen."
codeview:
title: "HTML-Code anzeigen"
content: "Über diese Schaltfläche kann der HTML-Code der Startseite direkt angezeigt und bearbeitet werden. Diese Vorgehensweise wird empfohlen, HTML-Kenntnisse sind vorausgesetzt."
reset:
title: "Rückgängig"
content: "Sie können jederzeit die Originalseite wiederherstellen, indem Sie hier klicken."
css:
title: "Stylesheet anpassen"
content: "Fortgeschrittene Benutzer können ein benutzerdefiniertes Stylesheet (CSS) für die Startseite erstellen."
about:
title: "Über"
content: "Passen Sie diese Seite vollständig an, um Ihre Aktivitäten vorzustellen."
privacy:
title: "Datenschutzerklärung"
content: "<p>Erklären Sie hier, wie die gesammelten Daten der Nutzer verwendet werden.</p><p>Die Datenschutzbestimmungen sehen eine Datenschutzerklärung vor sowie die Bestimmung eines Datenschutzbeauftragten.</p>"
draft:
title: "Entwurf"
content: "Klicken Sie hier für die Vorlage einer Datenschutzerklärung, die Sie nur lesen und vervollständigen müssen."
reservations:
title: "Reservierungen"
content: "Öffnungszeiten, Reservierungssstornierungen... Jedes Fablab hat seine eigenen Reservierungsregeln, die Sie auf dieser Seite festlegen können."
open_api:
welcome:
title: "OpenAPI"
content: "Fab-Manager bietet eine offene API an, über die externe Programme einfach auf Fab-Manager-Daten zugreifen können. Hier können Sie Zugriffe auf diese API gewähren."
doc:
title: "Dokumentation"
content: "Klicken Sie hier, um die API Online-Dokumentation aufzurufen."

View File

@ -346,7 +346,7 @@ en:
confirmation_required: "Confirmation required"
do_you_really_want_to_delete_this_coupon: "Do you really want to delete this coupon?"
coupon_was_successfully_deleted: "Coupon was successfully deleted."
unable_to_delete_the_specified_coupon_already_in_use: "Unable to delete the specified coupon: it is already used with some invoices."
unable_to_delete_the_specified_coupon_already_in_use: "Unable to delete the specified coupon: it is already used with some invoices and/or some payment schedules."
unable_to_delete_the_specified_coupon_an_unexpected_error_occurred: "Unable to delete the specified coupon: an unexpected error occurred."
send_a_coupon: "Send a coupon"
coupon: "Coupon"
@ -414,6 +414,7 @@ en:
credit_note: "Credit note"
display_more_invoices: "Display more invoices..."
no_invoices_for_now: "No invoices for now."
payment_schedules_list: "Payment schedules"
invoicing_settings: "Invoicing settings"
warning_invoices_disabled: "Warning : invoices are not enabled. No invoices will be generated by Fab-manager. Nevertheless, you must correctly fill the information below, especially VAT."
change_logo: "Change logo"
@ -639,6 +640,32 @@ en:
currency_info_html: "Please specify below the currency used for online payment. You should provide a three-letter ISO code, from the list of <a href='https://stripe.com/docs/currencies' target='_blank'>Stripe supported currencies</a>."
currency_alert_html: "<strong>Warning</strong>: the currency cannot be changed after the first online payment was made. Please define this setting carefully before opening Fab-manager to your members."
stripe_currency: "Stripe currency"
payment_schedules:
filter_schedules: "Filter schedules"
schedules_table:
schedule_num: "Schedule #"
date: "Date"
price: "Price"
customer: "Customer"
deadline: "Deadline"
amount: "Amount"
state: "State"
download: "Download"
state_new: "Not yet due"
state_pending: "Waiting for the cashing of the check"
state_requires_payment_method: "The credit card must be updated"
state_requires_action: "Action required"
state_paid: "Paid"
state_error: "Error"
method_stripe: "by card"
method_check: "by check"
confirm_payment: "Confirm payment"
solve: "Solve"
update_card: "Update the card"
document_filters:
reference: "Reference"
customer: "Customer"
date: "Date"
#management of users, labels, groups, and so on
members:
users_management: "Users management"

View File

@ -346,7 +346,7 @@ fr:
confirmation_required: "Confirmation requise"
do_you_really_want_to_delete_this_coupon: "Êtes-vous sûr(e) de vouloir supprimer ce code promotionnel ?"
coupon_was_successfully_deleted: "Le code promotionnel a bien été supprimé."
unable_to_delete_the_specified_coupon_already_in_use: "Impossible de supprimer le code promotionnel : il est utilisé dans des factures."
unable_to_delete_the_specified_coupon_already_in_use: "Impossible de supprimer le code promotionnel : il est utilisé dans des factures et/ou des échéanciers."
unable_to_delete_the_specified_coupon_an_unexpected_error_occurred: "Impossible de supprimer le code promotionnel : une erreur inattendue s'est produite."
send_a_coupon: "Envoyer un code promo"
coupon: "Code promo"
@ -414,6 +414,7 @@ fr:
credit_note: "Avoir"
display_more_invoices: "Afficher plus de factures..."
no_invoices_for_now: "Aucune facture pour le moment."
payment_schedules_list: "Échéanciers de paiement"
invoicing_settings: "Paramètres de facturation"
warning_invoices_disabled: "Attention : les factures ne sont pas activées. Aucune facture ne sera générée par Fab-manager. Vous devez néanmoins remplir correctement les informations ci-dessous, particulièrement la TVA."
change_logo: "Changer le logo"
@ -639,6 +640,32 @@ fr:
currency_info_html: "Veuillez indiquer la devise à utiliser lors des paiements en ligne. Vous devez fournir un code ISO à trois lettres, issu de la liste des <a href='https://stripe.com/docs/currencies' target='_blank'>devises supportées par Stripe</a>."
currency_alert_html: "<strong>Attention</strong> : la devise ne peut pas être modifiée après que le premier paiement en ligne ait été effectué. Veuillez définir attentivement ce paramètre avant d'ouvrir Fab-manager à vos membres."
stripe_currency: "Devise Stripe"
payment_schedules:
filter_schedules: "Filtrer les échéanciers"
schedules_table:
schedule_num: "Échéancier n°"
date: "Date"
price: "Prix"
customer: "Client"
deadline: "Échéance"
amount: "Montant"
state: "État"
download: "Télécharger"
state_new: "Pas encore à l'échéance"
state_pending: "En attente de l'encaissement du chèque"
state_requires_payment_method: "La carte bancaire doit être mise à jour"
state_requires_action: "Action requise"
state_paid: "Payée"
state_error: "Erreur"
method_stripe: "par carte"
method_check: "par chèque"
confirm_payment: "Confirmer l'encaissement"
solve: "Résoudre"
update_card: "Mettre à jour la carte"
document_filters:
reference: "Référence"
customer: "Client"
date: "Date"
#management of users, labels, groups, and so on
members:
users_management: "Gestion des utilisateurs"

View File

@ -0,0 +1,183 @@
de:
app:
logged:
#user's profile completion page when logging from an SSO provider
profile_completion:
confirm_your_new_account: "Bestätigen Sie Ihr neues Konto"
you_ve_just_created_a_new_account_on_the_fablab_by_logging_from: "Sie haben ein neues Konto auf {GENDER, select, neutral{} other{dem}} {NAME} erstellt, über Anmeldung von"
we_need_some_more_details: "Um die Einrichtung der Plattform abzuschließen, benötigen wir weitere Details"
your_email_is_already_used_by_another_account_on_the_platform: "Ihre E-Mail-Adresse scheint bereits von einem anderen Benutzer verwendet zu werden. Prüfen Sie bitte Ihr Postfach und geben Sie den Code ein, der Ihnen geschickt wurde."
or: "oder"
please_fill_the_following_form: "Bitte füllen Sie das folgende Formular aus"
some_data_may_have_already_been_provided_by_provider_and_cannot_be_modified: "Einige Daten wurden möglicherweise bereits von {NAME} bereitgestellt und können nicht geändert werden"
then_click_on_: "Dann klicken Sie auf"
_to_start_using_the_application: "um die Anwendung zu verwenden"
new_on_this_platform: "Neu auf dieser Plattform?"
your_email_: "Ihre E-Mail-Adresse"
_is_currently_associated_with_another_account_on_this_platform: "ist derzeit mit einem anderen Konto auf dieser Plattform verknüpft."
please_click_to_change_email_associated_with_your_PROVIDER_account: "Wenn es nicht Ihre Mailadresse ist, klicken Sie bitte auf den folgenden Button, um die E-Mail zu ändern, die mit Ihrem {PROVIDER} -Konto verknüpft ist."
do_you_already_have_an_account: "Haben Sie bereits ein Konto?"
do_not_fill_the_form_beside_but_specify_here_the_code_you_ve_received_by_email_to_recover_your_access: "Füllen Sie nicht das Formular aus. Geben Sie stattdessen hier den Code an, den Sie per E-Mail erhalten haben, um Ihren Zugang wiederherzustellen."
just_specify_code_here_to_recover_access: "Geben Sie hier den Code an, den Sie per E-Mail erhalten haben, um Ihren Zugriff wiederherzustellen."
i_did_not_receive_the_code: "Ich habe den Code nicht erhalten"
authentification_code: "Authentifizierungscode"
confirm_my_code: "Meinen Authentifizierungscode bestätigen"
an_unexpected_error_occurred_check_your_authentication_code: "Ein unerwarteter Fehler ist aufgetreten. Bitte überprüfen Sie Ihren Authentifizierungscode."
send_code_again: "Code erneut senden"
email_address_associated_with_your_account: "E-Mail-Adresse, die Ihrem Konto zugeordnet ist"
email_is_required: "E-Mail-Adresse ist erforderlich"
email_format_is_incorrect: "E-Mail-Format ist falsch"
code_successfully_sent_again: "Code erfolgreich erneut gesendet"
used_for_statistics: "Diese Daten werden für statistische Zwecke verwendet"
your_user_s_profile: "Ihr Benutzerprofil"
user_s_profile_is_required: "Benutzerprofil ist erforderlich."
i_ve_read_and_i_accept_: "Ich habe gelesen und akzeptiere"
_the_fablab_policy: "die FabLab Richtlinie"
change_my_data: "Meine Daten ändern"
sync_my_profile: "Mein Profil synchronisieren"
once_your_data_are_up_to_date_: "Sobald Ihre Daten auf dem neuesten Stand sind,"
_click_on_the_synchronization_button_opposite_: "klicken Sie auf den Synchronisation-Button gegenüber"
_disconnect_then_reconnect_: "trennen und erneut verbinden"
_for_your_changes_to_take_effect: "damit Ihre Änderungen wirksam werden."
dashboard:
#dashboard: public profile
profile:
empty: ''
#dashboard: edit my profile
settings:
last_activity_on_: "Letzte Aktivität am {DATE}"
i_want_to_change_group: "Ich möchte die Gruppe ändern!"
your_subscription_expires_on_: "Ihr Abonnement endet am"
no_subscriptions: "Keine Abonnements"
i_want_to_subscribe: "Ich möchte mich anmelden!"
to_come: "demnächst"
approved: "bestätigt"
projects: "Projekte"
no_projects: "Keine Projekte"
labels: "Labels"
no_labels: "Keine Labels"
cookies: "Cookies"
cookies_accepted: "Sie haben Cookies akzeptiert"
cookies_declined: "Sie haben Cookies abgelehnt"
cookies_unset: "Sie haben noch keine Cookie-Auswahl getroffen"
reset_cookies: "Meine Wahl ändern"
delete_my_account: "Mein Konto löschen"
edit_my_profile: "Mein Profil bearbeiten"
your_group_has_been_successfully_changed: "Ihre Gruppe wurde erfolgreich geändert."
an_unexpected_error_prevented_your_group_from_being_changed: "Ein unerwarteter Fehler verhinderte, dass Ihre Gruppe geändert wurde."
confirmation_required: "Bestätigung erforderlich"
confirm_delete_your_account: "Wollen Sie wirklich Ihr Konto löschen?"
all_data_will_be_lost: "Alle Ihre Daten werden gelöscht und können nicht wiederhergestellt werden."
invoicing_data_kept: "Nach geltender Gesetzeslage werden alle rechnungsrelevanten Daten für 10 Jahre separat aufbewahrt."
statistic_data_anonymized: "Einige Daten (Geschlecht, Geburtsdatum, Gruppe) werden anonymisiert und zu statistischen Zwecken gespeichert."
no_further_access_to_projects: "Ihre veröffentlichten Projekte werden anonymisiert, Sie werden keine Bearbeitungsmöglichkeit mehr haben."
your_user_account_has_been_successfully_deleted_goodbye: "Ihr Benutzerkonto wurde erfolgreich gelöscht. Auf Wiedersehen!"
an_error_occured_preventing_your_account_from_being_deleted: "Ein Fehler hat das Löschen Ihres Kontos verhindert."
used_for_statistics: "Diese Daten werden für statistische Zwecke verwendet"
used_for_invoicing: "Diese Daten werden für Abrechnungszwecke verwendet"
used_for_reservation: "Diese Daten werden im Fall einer Buchungsänderung verwendet"
used_for_profile: "Diese Daten werden nur auf Ihrem Profil angezeigt"
used_for_pricing_stats: "Diese Daten werden zur Bestimmung der Ihnen gewährten Preise und zu statistischen Zwecken verwendet"
public_profile: "Sie werden über ein öffentliches Profil verfügen, andere Nutzer können Sie in ihren Projekten einbinden"
trainings: "Schulungen"
no_trainings: "Keine Schulungen"
subscription: "Abonnement"
group: "Gruppe"
or: "oder"
confirm_changes: "Änderungen bestätigen"
change_my_data: "Meine Daten ändern"
sync_my_profile: "Mein Profil synchronisieren"
once_your_data_are_up_to_date_: "Sobald Ihre Daten auf dem neuesten Stand sind,"
_click_on_the_synchronization_button_opposite_: "klicken Sie auf den Synchronisation-Button gegenüber"
_disconnect_then_reconnect_: "trennen und erneut verbinden"
_for_your_changes_to_take_effect: "damit Ihre Änderungen wirksam werden."
#dashboard: my projects
projects:
you_dont_have_any_projects: "Sie haben keine Projekte."
add_a_project: "Projekt hinzufügen"
author: "Autor"
collaborator: "Mitarbeitende"
rough_draft: "Entwurf"
description: "Beschreibung"
machines_and_materials: "Maschinen und Materialien"
machines: "Maschinen"
materials: "Materialien"
collaborators: "Mitarbeitende"
#dashboard: my trainings
trainings:
your_next_trainings: "Ihre nächsten Schulungen"
your_previous_trainings: "Ihre vorigen Schulungen"
your_approved_trainings: "Ihre bestätigten Trainings"
no_trainings: "Keine Schulungen"
#dashboard: my events
events:
your_next_events: "Ihre nächsten Termine"
no_events_to_come: "Keine anzuzeigenden Termine"
your_previous_events: "Ihre vorherigen Termine"
no_passed_events: "Keine vergangenen Termine"
NUMBER_normal_places_reserved: "{NUMBER} {NUMBER, plural, one {} =0{} =1{normaler Platz reserviert} other{normale Plätze reserviert}}"
NUMBER_of_NAME_places_reserved: "{NUMBER} {NUMBER, plural, one {} =0{} =1{{NAME}-Platz reserviert} other{{NAME}-Plätze reserviert}}"
#dashboard: my invoices
invoices:
reference_number: "Referenznummer"
date: "Datum"
price: "Preis"
download_the_invoice: "Rechnung herunterladen"
download_the_credit_note: "Rückerstattungsrechnung herunterladen"
no_invoices_for_now: "Momentan keine Rechnungen."
#public profil of a member
members_show:
members_list: "Mitgliederliste"
#list of members accepting to be contacted
members:
the_fablab_members: "Die FabLab-Mitglieder"
display_more_members: "Weitere Mitglieder anzeigen..."
no_members_for_now: "Keine Mitglieder im Moment"
avatar: "Benutzerbild"
user: "Nutzer"
pseudonym: "Pseudonym"
email_address: "EMailAdresse"
#add a new project
projects_new:
add_a_new_project: "Neues Projekt hinzufügen"
#modify an existing project
projects_edit:
edit_the_project: "Projekt bearbeiten"
rough_draft: "Entwurf"
publish: "Veröffentlichen"
#book a machine
machines_reserve:
machine_planning: "Belegungsplan"
i_ve_reserved: "Ich habe reserviert"
not_available: "Nicht verfügbar"
i_reserve: "Ich reserviere"
i_shift: "Ich verschiebe"
i_change: "Ich ändere"
do_you_really_want_to_cancel_this_reservation: "Diese Reservierung stornieren?"
reservation_was_cancelled_successfully: "Die Reservierung wurde erfolgreich storniert."
cancellation_failed: "Stornierung fehlgeschlagen."
a_problem_occured_during_the_payment_process_please_try_again_later: "Während des Zahlungsvorgangs ist ein Problem aufgetreten. Bitte versuchen Sie es später erneut."
#book a training
trainings_reserve:
trainings_planning: "Schulungsplanung"
planning_of: "Planung von " #eg. Planning of 3d printer training
all_trainings: "Alle Schulungen"
cancel_my_selection: "Auswahl aufheben"
i_change: "Ich ändere"
i_shift: "Ich verschiebe"
i_ve_reserved: "Ich reservierte"
#book a space
space_reserve:
planning_of_space_NAME: "Planung des {NAME} Raumes"
i_ve_reserved: "Ich reservierte"
i_shift: "Ich verschiebe"
i_change: "Ich ändere"
notifications:
notifications_center: "Mitteilungszentrale"
mark_all_as_read: "Alle als gelesen markieren"
date: "Datum"
notif_title: "Titel"
no_new_notifications: "Keine neuen Benachrichtigungen."
archives: "Archiv"
no_archived_notifications: "Keine archivierten Benachrichtigungen."
load_the_next_notifications: "Lade die nächsten Benachrichtigungen..."

View File

@ -0,0 +1,449 @@
de:
app:
public:
#header and "about" page
common:
about_the_fablab: "Über {GENDER, select, male{den} female{die} neutral{} other{das}} {NAME}"
return: "Zurück"
#cookies
cookies:
about_cookies: "Diese Website verwendet Cookies zur Reichweitenmessung."
learn_more: "Mehr erfahren"
accept: "Cookies akzeptieren"
decline: "Ablehnen"
#dashboard sections
dashboard: "Dashboard"
my_profile: "Mein Profil"
my_settings: "Persönliche Einstellungen"
my_projects: "Meine Projekte"
my_trainings: "Meine Trainings"
my_events: "Meine Veranstaltungen"
my_invoices: "Meine Rechnungen"
my_wallet: "Mein Guthaben"
#contextual help
help: "Hilfe"
#login/logout
sign_out: "Abmelden"
sign_up: "Registrieren"
sign_in: "Anmelden"
#left menu
notifications: "Mitteilungen"
admin: "Admin"
manager: "Manager"
reduce_panel: "Navigatiion reduzieren"
#left menu (public)
home: "Start"
reserve_a_machine: "Maschine reservieren"
trainings_registrations: "Schulungen - Anmeldung"
events_registrations: "Veranstaltungen - Anmeldung"
reserve_a_space: "Platz reservieren"
projects_gallery: "Projekt-Galerie"
subscriptions: "Abonnements"
public_calendar: "Kalender"
#left menu (admin)
trainings_monitoring: "Schulungen"
manage_the_calendar: "Kalender"
manage_the_users: "Benutzer"
manage_the_invoices: "Rechnungen"
subscriptions_and_prices: "Abonnements und Preise"
manage_the_events: "Veranstaltungen"
manage_the_machines: "Maschinen"
manage_the_spaces: "Räume"
projects: "Projekte"
statistics: "Statistiken"
customization: "Anpassung"
open_api_clients: "OpenAPI-Clients"
#account creation modal
create_your_account: "Eigenen Account erstellen"
man: "Männlich"
woman: "Weiblich"
gender_is_required: "Die Angabe des Geschlechts ist erforderlich."
your_first_name: "Dein Vorname"
first_name_is_required: "Der Vorname ist erforderlich."
your_surname: "Dein Nachname"
surname_is_required: "Nachname ist erforderlich."
your_pseudonym: "Dein Pseudonym"
pseudonym_is_required: "Pseudonym ist erforderlich."
your_email_address: "Deine E-Mail-Adresse"
email_is_required: "E-Mail-Adresse ist erforderlich."
your_password: "Passwort"
password_is_required: "Passwort ist erforderlich."
password_is_too_short: "Paßwort ist zu kurz (mindestens 8 Zeichen)"
type_your_password_again: "Passwort erneut eingeben"
password_confirmation_is_required: "Passwortbestätigung ist erforderlich."
password_does_not_match_with_confirmation: "Die beiden Passworteingaben sind nicht identisch."
i_am_an_organization: "Ich bin eine Organisation"
name_of_your_organization: "Geben Sie den Namen ihrer Organisation ein"
organization_name_is_required: "Name der Organisation ist erforderlich."
address_of_your_organization: "Adresse Ihrer Organisation"
organization_address_is_required: "Adresse der Organisation ist erforderlich."
your_user_s_profile: "Dein Benutzerprofil"
user_s_profile_is_required: "Benutzerprofil ist erforderlich."
birth_date: "Geburtsdatum"
birth_date_is_required: "Geburtsdatum ist erforderlich."
phone_number: "Telefonnummer"
phone_number_is_required: "Die Angabe der Telefonnummer ist erforderlich."
i_authorize_Fablab_users_registered_on_the_site_to_contact_me: "Angemeldete Benutzer dürfen mich kontaktieren"
i_accept_to_receive_information_from_the_fablab: "Das Fablab darf mir Informationen schicken"
i_ve_read_and_i_accept_: "Ich habe gelesen und akzeptiere"
_the_fablab_policy: "die FabLab Richtlinie"
field_required: "Erforderliche Felder"
unexpected_error_occurred: "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es später erneut."
used_for_statistics: "Diese Daten werden für statistische Zwecke verwendet"
used_for_invoicing: "Diese Daten werden für Abrechnungszwecke verwendet"
used_for_reservation: "Diese Daten werden im Fall einer Buchungsänderung verwendet"
used_for_profile: "Diese Daten werden nur auf deinem Profil angezeigt"
public_profile: "Sie werden über ein öffentliches Profil verfügen, andere Nutzer können Sie in ihren Projekten einbinden"
you_will_receive_confirmation_instructions_by_email_detailed: "In wenigen Minuten wirst Du eine Email erhalten mit der du deine Anmeldung bestätigen kannst."
#password modification modal
change_your_password: "Passwort ändern"
your_new_password: "Ihr neues Passwort"
your_password_was_successfully_changed: "Ihr Passwort wurde erfolgreich geändert."
#connection modal
connection: "Anmelden"
password_forgotten: "Passwort vergessen?"
confirm_my_account: "E-mail bestätigen"
not_registered_to_the_fablab: "Nicht bei FabLab registriert?"
create_an_account: "Erstelle ein Konto"
wrong_email_or_password: "Falsche E-Mail Adresse oder Passwort."
caps_lock_is_on: "Feststelltaste ist aktiviert"
#confirmation modal
you_will_receive_confirmation_instructions_by_email: "Sie erhalten eine Bestätigungsanleitung per E-Mail."
#forgotten password modal
your_email_address_is_unknown: "Ihre E-Mail-Adresse ist unbekannt."
you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password: "Sie erhalten in Kürze eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts."
#Fab-manager's version
version: "Version:"
upgrade_fabmanager: "Fab-Manager aktualisieren"
current_version: "Sie verwenden derzeit Version {VERSION} von Fab-Manager."
upgrade_to: "Eine neue Version ist verfügbar. Sie können bis zu Version {VERSION} upgraden."
read_more: "Details dieser Version ansehen"
security_version_html: "<strong>Ihre aktuelle Version ist unsicher!</strong><br> Eine neue Version mit Sicherheitsupdates ist verfügbar. Aktualisieren Sie so bald wie möglich!"
how_to: "So können Sie upgraden"
#Notifications
and_NUMBER_other_notifications: "und {NUMBER, plural, one {} =0{keine weiteren Benachrichtigungen} =1{eine weitere Benachrichtigung} other{{NUMBER} weitere Benachrichtigungen}}..."
#about page
about:
read_the_fablab_policy: "Lesen Sie die FabLab-Richtlinie"
read_the_fablab_s_general_terms_and_conditions: "Lesen Sie die allgemeinen Geschäftsbedingungen des FabLabs"
your_fablab_s_contacts: "Ihre FabLab-Kontakte"
privacy_policy: "Datenschutzerklärung"
#'privacy policy' page
privacy:
title: "Datenschutzerklärung"
dpo: "Datenschutzbeauftragter"
last_update: "Letztes Update,"
#home page
home:
latest_documented_projects: "Die neuesten dokumentierten Projekte"
follow_us: "Folge uns"
latest_tweets: "Die neuesten Tweets"
latest_registered_members: "Neueste registrierte Mitglieder"
create_an_account: "Neues Konto einrichten"
discover_members: "Mitglieder entdecken"
#next events summary on the home page
fablab_s_next_events: "Fablab´s nächste Veranstaltungen"
every_events: "Alle Veranstaltungen"
from_date_to_date: "Von {START} bis {END}"
on_the_date: "Am {DATE}"
from_time_to_time: "Von {START} bis {END}"
without_reservation: "Ohne Reservierung"
free_admission: "Freier Zugang"
full_price: "Voller Preis: "
event_full: "Event ausgebucht"
still_available: "Verfügbare Plätze: "
all_day: "Ganztägig"
#projects gallery
projects_list:
the_fablab_projects: "Die Fab Lab-Projekte"
add_a_project: "Projekt hinzufügen"
search_over_the_whole_network: "Suche über das gesamte Fab-Manager-Netzwerk"
tooltip_openlab_projects_switch: "Mit der Suche über das gesamte Netzwerk können Sie die Projekte aller Fab-Manager durchsuchen, die diese Funktion nutzen!"
openlab_search_not_available_at_the_moment: "Suche über das gesamte Netzwerk ist derzeit nicht verfügbar. Sie können nach Projekten auf dieser Plattform suchen."
project_search_result_is_empty: "Leider haben wir keine Ergebnisse gefunden, die Ihren Suchkriterien entsprechen."
reset_all_filters: "Alle Filter zurücksetzen"
search: "Suche"
all_projects: "Alle Projekte"
my_projects: "Meine Projekte"
projects_to_whom_i_take_part_in: "Projekte, an denen ich beteiligt bin"
all_machines: "Alle Maschinen"
all_themes: "Alle Themen"
all_materials: "Alle Materialien"
load_next_projects: "Nächste Projekte laden"
rough_draft: "Grober Entwurf"
#details of a projet
projects_show:
rough_draft: "Entwurf"
project_description: "Projektbeschreibung"
by_name: "Von {NAME}"
step_N: "Schritt {INDEX}"
share_on_facebook: "Auf Facebook teilen"
share_on_twitter: "Auf Twitter teilen"
deleted_user: "Gelöschter Nutzer"
posted_on_: "Gepostet am"
CAD_file_to_download: "{COUNT, plural, one {} =0{Keine CAD-Dateien} =1{CAD-Datei zum Download} other{CAD-Dateien zum Download}}"
machines_and_materials: "Maschinen und Materialien"
collaborators: "Mitarbeitende"
licence: "Lizenz"
confirmation_required: "Bestätigung erforderlich"
report_an_abuse: "Missbrauch melden"
unauthorized_operation: "Unerlaubter Vorgang"
your_report_was_successful_thanks: "Deine Meldung wurde verschickt - vielen Dank."
an_error_occured_while_sending_your_report: "Beim Senden Ihrer Meldung trat ein Fehler auf."
your_first_name: "Ihr Vorname"
your_first_name_is_required: "Der Vorname ist erforderlich."
your_surname: "Ihr Nachname"
your_surname_is_required: "Der Nachname ist erforderlich."
your_email_address: "Ihre E-Mail-Adresse"
your_email_address_is_required: "Die E-Mail-Adresse ist erforderlich."
tell_us_why_this_looks_abusive: "Erklären Sie, warum das beleidigend wirkt"
message_is_required: "Nachricht erforderlich."
report: "Melden"
do_you_really_want_to_delete_this_project: "Wollen Sie dieses Projekt wirklich löschen?"
#list of machines
machines_list:
the_fablab_s_machines: "Die Maschinen des FabLabs"
add_a_machine: "Maschine hinzufügen"
new_availability: "Verfügbare Reservierungen"
book: "Buchen"
_or_the_: " oder die "
status_enabled: "Aktiviert"
status_disabled: "Deaktiviert"
status_all: "Alle"
#details of a machine
machines_show:
book_this_machine: "Diese Maschine buchen"
technical_specifications: "Technische Spezifikationen"
files_to_download: "Dateien zum Herunterladen"
projects_using_the_machine: "Projekte mit der Maschine"
_or_the_: " oder die "
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_machine: "Möchten Sie diese Maschine wirklich löschen?"
unauthorized_operation: "Unerlaubter Vorgang"
the_machine_cant_be_deleted_because_it_is_already_reserved_by_some_users: "Die Maschine kann nicht gelöscht werden, da sie bereits von einigen Benutzern reserviert ist."
#list of trainings
trainings_list:
book: "Buchen"
the_trainings: "Schulungen"
#details of a training
training_show:
book_this_training: "Diese Schulung buchen"
do_you_really_want_to_delete_this_training: "Möchten Sie diese Schulung wirklich löschen?"
unauthorized_operation: "Unerlaubter Vorgang"
confirmation_required: "Bestätigung erforderlich"
the_training_cant_be_deleted_because_it_is_already_reserved_by_some_users: "Die Schulung kann nicht gelöscht werden, da sie bereits von einigen Benutzern gebucht ist."
#summary of the subscriptions
plans:
subscriptions: "Abonnements"
i_choose_that_plan: "Ich wähle dieses Abo"
i_subscribe_online: "Ich abonniere online"
i_already_subscribed: "Ich habe bereits abonniert"
more_information: "Weitere Informationen"
your_subscription_expires_on_the_DATE: "Ihr Abonnement läuft ab am {DATE}"
no_plans: "Für Ihre Gruppe sind keine Pläne verfügbar"
my_group: "Meine Gruppe"
his_group: "{GENDER, select, male{Seine} female{Ihre} other{Seine}} Gruppe"
he_wants_to_change_group: "{ROLE, select, member{Ich möchte} other{Der Benutzer möchte}} die Gruppe wechseln"
change_my_group: "Ändere {ROLE, select, member{meine} other{{GENDER, select, male{seine} female{ihre} other{seine}}}} Gruppe"
summary: "Zusammenfassung"
your_subscription_has_expired_on_the_DATE: "Ihr Abonnement ist am {DATE} abgelaufen"
subscription_price: "Abonnementspreis"
you_ve_just_selected_a_subscription_html: "Sie haben ein <strong>Abonnement</strong> ausgewählt:"
confirm_and_pay: "Bestätigen und bezahlen"
you_ve_just_payed_the_subscription_html: "Sie bezahlten das <strong>Abonnement</strong>:"
thank_you_your_subscription_is_successful: "Vielen Dank. Ihr Abonnement ist erfolgt!"
your_invoice_will_be_available_soon_from_your_dashboard: "Ihre Rechnung wird bald in Ihrem Dashboard verfügbar sein"
your_group_was_successfully_changed: "Ihre Gruppe wurde erfolgreich geändert."
the_user_s_group_was_successfully_changed: "Die Gruppe des Nutzers wurde erfolgreich geändert."
an_error_prevented_your_group_from_being_changed: "Ein Fehler verhinderte das Ändern Ihrer Gruppe."
an_error_prevented_to_change_the_user_s_group: "Fehler beim Ändern der Benutzergruppe."
an_error_occured_during_the_payment_process_please_try_again_later: "Beim Zahlungsvorgang ist ein Problem aufgetreten. Bitte versuchen Sie es später erneut."
subscription_confirmation: "Abonnementbestätigung"
here_is_the_NAME_subscription_summary: "Hier ist die Zusammenfassung des {NAME}-Abonnements:"
confirm_payment_of_html: "{ROLE, select, admin{Bezahlung vor Ort} other{Bezahlen}}: {AMOUNT}" #(contexte : validate a payment of $20,00)
online_payment_disabled: "Zahlung per Kreditkarte ist nicht möglich. Bitte kontaktieren Sie die FabLab Rezeption direkt."
#Fablab's events list
events_list:
the_fablab_s_events: "Veranstaltungen des Fablabs"
all_categories: "Alle Kategorien"
for_all: "Für alle"
sold_out: "Ausverkauft"
cancelled: "Storniert"
free_admission: "Freier Zugang"
still_available: "verfügbare Plätze"
without_reservation: "Ohne Reservierung"
add_an_event: "Veranstaltung hinzufügen"
load_the_next_events: "Die nächsten Events laden..."
full_price_: "Voller Preis:"
to_date: "bis" #eg. from 01/01 to 01/05
all_themes: "Alle Themen"
#details and booking of an event
events_show:
event_description: "Beschreibung"
downloadable_documents: "Herunterladbare Dokumente"
information_and_booking: "Information und Buchung"
dates: "Datum"
beginning: "Beginn:"
ending: "Endet:"
opening_hours: "Öffnungszeiten:"
all_day: "Ganztägig"
from_time: "Von" #eg. from 18:00 to 21:00
to_time: "bis" #eg. from 18:00 to 21:00
full_price_: "Voller Preis:"
tickets_still_availables: "noch verfügbare Tickets:"
sold_out: "Ausverkauft."
without_reservation: "Ohne Reservierung"
cancelled: "Storniert"
ticket: "{NUMBER, plural, one{Ticket} other{Tickets}}"
make_a_gift_of_this_reservation: "Diese Reservierung verschenken"
thank_you_your_payment_has_been_successfully_registered: "Vielen Dank. Ihre Zahlung wurde erfolgreich gebucht!"
you_can_find_your_reservation_s_details_on_your_: "Sie finden die Reservierungsdetails in Ihrem"
dashboard: "Dashboard"
you_booked_DATE: "Sie haben gebucht ({DATE}):"
canceled_reservation_SEATS: "Reservierung storniert ({SEATS} Plätze)"
book: "Buchen"
confirm_and_pay: "Bestätigen und bezahlen"
confirm_payment_of_html: "{ROLE, select, admin{Bezahlung vor Ort} other{Bezahlen}}: {AMOUNT}" #(contexte : validate a payment of $20,00)
online_payment_disabled: "Zahlung per Kreditkarte ist nicht möglich. Bitte kontaktieren Sie die FabLab Rezeption direkt."
please_select_a_member_first: "Bitte wählen Sie zuerst ein Mitglied"
change_the_reservation: "Reservierung ändern"
you_can_shift_this_reservation_on_the_following_slots: "Sie können diese Reservierung auf die folgenden Slots verschieben:"
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_event: "Möchten Sie diese Veranstaltung wirklich löschen?"
delete_recurring_event: "Sie sind dabei, eine wiederkehrende Veranstaltung zu löschen. Was möchten Sie tun?"
delete_this_event: "Nur diese Veranstaltung"
delete_this_and_next: "Diese Veranstaltung sowie die folgenden"
delete_all: "Alle Veranstaltungen"
event_successfully_deleted: "Veranstaltung erfolgreich gelöscht."
events_deleted: "Die Veranstaltung sowie {COUNT, plural, one {} =1{eine weitere} other{{COUNT} weitere}} wurden gelöscht"
unable_to_delete_the_event: "Das Ereignis kann nicht gelöscht werden, es wurde möglicherweise von einem Mitglied gebucht"
events_not_deleted: "Von {TOTAL} Veranstaltungen {COUNT, plural, one {} =1{wurde eine nicht gelöscht} other{wurden {COUNT} nicht gelöscht}}. Möglicherweise {COUNT, plural, =1{ist sie} other{sind sie}} bereits reserviert."
cancel_the_reservation: "Reservierung stornieren"
do_you_really_want_to_cancel_this_reservation_this_apply_to_all_booked_tickets: "Möchten Sie diese Reservierung wirklich stornieren? Dies gilt für alle gebuchten Tickets."
reservation_was_successfully_cancelled: "Reservierung wurde erfolgreich storniert."
cancellation_failed: "Stornierung fehlgeschlagen."
event_is_over: "Die Veranstaltung ist vorbei."
thanks_for_coming: "Vielen Dank für Ihr Kommen!"
view_event_list: "Kommende Veranstaltungen anzeigen"
share_on_facebook: "Auf Facebook teilen"
share_on_twitter: "Auf Twitter teilen"
#public calendar
calendar:
calendar: "Kalender"
show_unavailables: "Nicht verfügbare Slots anzeigen"
filter_calendar: "Kalender filtern"
trainings: "Schulungen"
machines: "Maschinen"
spaces: "Räume"
events: "Veranstaltungen"
externals: "Andere Kalender"
#list of spaces
spaces_list:
the_spaces: "Die Räume"
new_availability: "Verfügbare Reservierungen"
add_a_space: "Raum hinzufügen"
status_enabled: "Aktiviert"
status_disabled: "Deaktiviert"
status_all: "Alle"
book: "Buchen"
#display the details of a space
space_show:
book_this_space: "Diesen Platz buchen"
unauthorized_operation: "Unerlaubter Vorgang"
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_space: "Wollen Sie diesen Raum wirklich löschen?"
the_space_cant_be_deleted_because_it_is_already_reserved_by_some_users: "Der Raum konnte nicht gelöscht werden, da er bereits von Nutzern reserviert wurde."
characteristics: "Eigenschaften"
files_to_download: "Dateien zum Herunterladen"
projects_using_the_space: "Projekte, die den Raum nutzen"
tour:
conclusion:
title: "Vielen Dank für Ihre Aufmerksamkeit"
content: "<p>Um diese kontextabhängige Hilfe neu zu starten, können Sie jederzeit <strong>F1</strong> drücken oder klicken Sie im Benutzermenu auf [? Hilfe].</p><p>Zusätzliche Hilfe finden Sie in der <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.5.pdf' target='_blank'>Benutzeranleitung</a> (nur auf Französisch).</p><p>Das Fab-Manager-Team bietet auch personalisierten Support (Hilfe beim Einstieg, Hilfe bei der Installation, Anpassung etc.), <a href='mailto:contact@fab-manager.com'>kontaktieren Sie uns</a> für weitere Informationen.</p>"
welcome:
welcome:
title: "Willkommen bei Fab-Manager"
content: "Zum leichteren Einstieg in die Anwendung bieten wir eine schnelle Tour über die Funktionen."
home:
title: "Startseite"
content: "Wenn Du hier klickst, kommst du zurück zur Homepage, auf der du dich gerade befindest."
machines:
title: "Maschinen"
content: "<p>Auf dieser Seite können Sie die Liste aller Maschinen einsehen und einen Slot im Namen eines Mitglieds reservieren.</p><p>Eine Maschine kann zum Beispiel ein 3D-Drucker sein.</p><p>Mitglieder können auch auf diese Seite zugreifen und eine Maschine selbst reservieren wenn Kreditkartenzahlung aktiviert ist, oder wenn einige Preise gleich 0 sind.</p>"
trainings:
title: "Schulungen"
content: "<p>Auf dieser Seite können Sie die Liste aller Schulungen einsehen und ein Mitglied für eine Schulung registrieren.</p><p>Trainings können als Voraussetzungen gesetzt werden, bevor die Reservierung bestimmter Maschinen erlaubt wird.</p><p>Mitglieder können auch auf diese Seite zugreifen und sich für eine Schulung registrieren wenn Kreditkartenzahlung aktiviert ist, oder wenn einige Preise gleich 0 sind.</p>"
spaces:
title: "Räume"
content: "<p>Auf dieser Seite können Sie die Liste aller verfügbaren Räume einsehen und einen Slot im Namen eines Mitglieds reservieren.</p><p>Ein Raum kann beispielsweise ein Meetingraum oder eine Holzwerkstatt sein.</p><p>Die Besonderheit von Räumen ist, dass sie von mehreren Mitgliedern gleichzeitig gebucht werden können. </p><p>Mitglieder können auf diese Seite zugreifen und selbst eine Maschine reservieren, wenn Kreditkartenzahlung aktiviert ist oder wenn einige Preise gleich 0 sind.</p>"
events:
title: "Veranstaltungen"
content: "<p>Ein Tag der offenen Tür oder ein Kurzworkshop zum Schreibtischlampenbau? Hier drüben!</p><p>Veranstaltungen können gratis oder kostenpflichtig (mit Möglichkeit zur Preisstaffelung) sein, frei zugänglich oder reservierungspflichtig.</p><p>Auch hier haben Mitglieder Seitenzugriff und können Plätze für kostenlose Veranstaltungen buchen bzw. auch für eintrittspflichtige, wenn Kreditkartenzahlung aktiviert ist.</p>"
calendar:
title: "Terminübersicht"
content: "Visualisieren Sie auf einen Blick alles, was für die nächsten Wochen geplant ist (Veranstaltungen, Schulungen, Maschinen etc.)."
projects:
title: "Projekte"
content: "<p>Dokumentieren und teilen Sie Projekte mit der Community.</p><p>Wenn Sie OpenLab nutzen, haben SIe Zugriff auf die Projekte des gesamten Fab-Manager-Netzwerks. <a href='mailto:contact@fab-manager.com'>Kontaktieren Sie uns</a> für den kostenlosen Zugang!</p>"
plans:
title: "Abonnements"
content: "Abonnements bieten eine Möglichkeit, Ihre Preise zu segmentieren und Vorteile für regelmäßige Nutzer zu bieten."
admin:
title: "{ROLE} -Abschnitt"
content: "<p>Alle Elemente unterhalb sind nur für Administratoren und Manager zugänglich. Mit ihnen wird Fab-Manager verwaltet und konfiguriert.</p><p>Anklicken, um jeweils mehr zu erfahren.</p>"
about:
title: "Über"
content: "Eine Seite, die Sie vollständig anpassen können, um Aktivitäten und Struktur Ihres Fablabs darzustellen."
notifications:
title: "Mitteilungszentrale"
content: "<p>Jedes Mal, wenn etwas Wichtiges passiert (Reservierungen, Kontoerstellung, Aktivitäten der Mitglieder usw.), werden Sie hier benachrichtigt.</p><p>Auch Ihre Mitglieder erhalten dort Benachrichtigungen.</p>"
profile:
title: "Benutzermenü"
content: "<p>zugriff auf Ihre persönlichen Informationen sowie Ihre Aktivitäten auf Fab-Manager.</p><p>Dieser Bereich ist auch jeweils für die Mitglieder verfügbar.</p>"
news:
title: "Neuigkeiten"
content: "<p>In diesem Bereich können Sie Neuigkeiten anzeigen lassen.</p><p>Inhalte können Sie leicht unter « Anpassen », « Startseite » ändern.</p>"
last_projects:
title: "Letzte Projekte"
content: "<p>Dieses Karussell scrollt durch die neuesten von Ihren Mitgliedern dokumentierten Projekte.</p>"
last_tweet:
title: "Letzter Tweet"
content: "<p>Der letzte Tweet Ihres Tweeter-Feeds kann hier angezeigt werden.</p><p>Konfigurieren Sie ihn unter « Anpassen », « Startseite ».</p>"
last_members:
title: "Neueste Mitglieder"
content: "Hier werden die letzten registrierten Mitglieder angezeigt, die ihre Adresse validiert und dem Kontaktieren zugestimmt haben."
next_events:
title: "Kommende Veranstaltungen"
content: "Die nächsten drei geplanten Veranstaltungen werden in diesem Bereich angezeigt."
customize:
title: "Startseite anpassen"
content: "<p>Diese Seite kann vollständig personalisiert werden.</p><p>Sie können <a href='mailto:contact@fab-manager.com'>uns kontaktieren</a> um eine maßgeschneiderte Anpassung der Startseite vorzunehmen.</p>"
version:
title: "Programmversion"
content: "Bewegen Sie den Cursor über dieses Symbol, um die Version von Fab-Manager anzuzeigen. Wenn Sie nicht die aktuellste Version verwenden, wird das hier angezeigt. Per Klick erhalten Sie weitere Informationen."
machines:
welcome:
title: "Maschinen"
content: "<p>Maschinen sind die Werkzeuge, die Ihren Nutzern zur Verfügung stehen. Maschinen, die von den Mitgliedern reserviert werden können, müssen hier erstellt werden.</p><p>Sie können auch nicht buchbare oder frei verfügbare Maschinen anlegen, diesen sollten keine Verfügbarkeits-Slots zugewiesen werden.</p>"
welcome_manager:
title: "Maschinen"
content: "Maschinen sind die Werkzeuge, die von Nutzern reserviert werden können."
view:
title: "Ansicht"
content: "Um eine Maschine zu ändern oder zu löschen, klicken Sie bitte zuerst hier. Maschinen mit verknüpften Verfügbarkeits-Slots können nicht gelöscht, aber deaktiviert werden."
reserve:
title: "Reservieren"
content: "Klicken Sie hier, um zu einer Übersicht der freien Slots zu gelangen. Dort können Sie diese Maschine für einen Benutzer buchen und bestehende Reservierungen verwalten."
spaces:
welcome:
title: "Räume"
content: "<p>Räume sind Orte für deine Nutzer, beispielsweise ein Meetingraum oder eine Holzwerkstatt. Räume, die von Nutzern reserviert werden können, müssen hier angelegt werden.</p><p>Das Besondere an Räumen ist, dass sie von mehreren Benutzern gleichzeitig reserviert werden können.</p>"
welcome_manager:
title: "Räume"
content: "<p>Räume sind Orte, die von Nutzern reserviert werden können, beispielsweise ein Meetingraum oder eine Holzwerkstatt. </p><p>Das Besondere an Räumen ist, dass sie von mehreren Benutzern gleichzeitig reserviert werden können.</p>"
view:
title: "Ansicht"
content: "Um einer Raum zu ändern oder zu löschen, klicken Sie bitte zuerst hier. Räume mit verknüpften Verfügbarkeits-Slots können nicht gelöscht, aber deaktiviert werden."
reserve:
title: "Reservieren"
content: "Klicken Sie hier, um zu einer Übersicht der freien Slots zu gelangen. Dort können Sie diesen Raum für einen Benutzer buchen und bestehende Reservierungen verwalten."

View File

@ -0,0 +1,446 @@
de:
app:
shared:
#translations of common buttons
buttons:
confirm_changes: "Änderungen bestätigen"
consult: "Beschreibung"
edit: "Bearbeiten"
change: "Ändern"
delete: "Löschen"
browse: "Durchsuchen"
cancel: "Abbrechen"
close: "Schließen"
clear: "Leeren"
today: "Heute"
confirm: "Bestätigen"
save: "Speichern"
"yes": "Ja"
"no": "Nein"
apply: "Anwenden"
messages:
you_will_lose_any_unsaved_modification_if_you_quit_this_page: "Sie verlieren jede ungespeicherte Änderung, wenn Sie diese Seite verlassen"
you_will_lose_any_unsaved_modification_if_you_reload_this_page: "Ungespeicherte Änderungen gehen verloren, wenn Sie die Seite neu laden"
payment_card_error: "Mit Ihrer Kreditkarte ist ein Problem aufgetreten:"
#user edition form
user:
man: "Männlich"
woman: "Weiblich"
add_an_avatar: "Avatar hinzufügen"
pseudonym: "Pseudonym"
pseudonym_is_required: "Pseudonym ist erforderlich."
first_name: "Ihr Vorname"
first_name_is_required: "Der Vorname ist erforderlich."
surname: "Ihr Nachname"
surname_is_required: "Der Nachname ist erforderlich."
email_address: "EMailAdresse"
email_address_is_required: "Die E-Mail-Adresse ist erforderlich."
change_password: "Passwort ändern"
new_password: "Neues Passwort"
password_is_required: "Passwort ist erforderlich."
password_is_too_short: "Passwort ist zu kurz (mindestens 8 Zeichen erforderlich)"
confirmation_of_new_password: "Neues Passwort bestätigen"
confirmation_of_password_is_required: "Passwortbestätigung ist erforderlich."
confirmation_of_password_is_too_short: "Die Passwortbestätigung ist zu kurz (mindestens 8 Zeichen)."
confirmation_mismatch_with_password: "Bestätigung stimmt nicht mit Passwort überein."
organization_name: "Name der Organisation"
organization_address: "Adresse der Organisation"
date_of_birth: "Geburtsdatum"
date_of_birth_is_required: "Geburtsdatum ist erforderlich."
website: "Website"
job: "Beruf/Tätigkeit"
interests: "Interessen"
CAD_softwares_mastered: "Kenntnisse in CAD-Software"
birthday: "Geburtsdatum"
birthday_is_required: "Das Geburtsdatum ist erforderlich."
address: "Adresse"
phone_number: "Telefonnummer"
phone_number_is_required: "Die Angabe der Telefonnummer ist erforderlich."
i_authorize_Fablab_users_registered_on_the_site_to_contact_me: "Angemeldete Benutzer dürfen mich kontaktieren"
i_accept_to_receive_information_from_the_fablab: "I accept to receive information from the FabLab"
used_for_statistics: "Diese Daten werden für statistische Zwecke verwendet"
used_for_invoicing: "Diese Daten werden für Abrechnungszwecke verwendet"
used_for_reservation: "Diese Daten werden im Fall einer Buchungsänderung verwendet"
used_for_profile: "Diese Daten werden nur auf Ihrem Profil angezeigt"
#project edition form
project:
name: "Name"
name_is_required: "Name ist erforderlich."
illustration: "Ansicht"
add_an_illustration: "Illustration hinzufügen"
CAD_file: "CAD-Datei"
allowed_extensions: "Zugelassene Dateitypen:"
add_a_new_file: "Neue Datei hinzufügen"
description: "Beschreibung"
description_is_required: "Beschreibung ist erforderlich."
steps: "Schritte"
step_N: "Schritt {INDEX}"
step_title: "Titel des Schrits"
add_a_picture: "Ein Bild hinzufügen"
change_the_picture: "Bild ändern"
delete_the_step: "Diesen Schritt löschen"
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_step: "Möchten Sie diesen Schritt wirklich löschen?"
add_a_new_step: "Neuen Schritt hinzufügen"
publish_your_project: "Projekt veröffentlichen"
or: "oder"
employed_materials: "Verwendetes Material"
employed_machines: "Verwendete Maschinen"
collaborators: "Mitarbeitende"
creative_commons_licences: "Creative Commons-Lizenzen"
themes: "Themen"
tags: "Stichwörter"
save_as_draft: "Als Entwurf speichern"
#machine edition form
machine:
name: "Name"
name_is_required: "Name ist erforderlich."
illustration: "Ansicht"
add_an_illustration: "Foto hinzufügen"
description: "Beschreibung"
description_is_required: "Beschreibung ist erforderlich."
technical_specifications: "Techische Daten"
technical_specifications_are_required: "Technische Spezifikationen sind erforderlich."
attached_files_pdf: "Dateianhänge (pdf)"
attach_a_file: "Eine Datei anfügen"
add_an_attachment: "Anhang hinzufügen"
disable_machine: "Maschine deaktivieren"
validate_your_machine: "Bestätigen Sie Ihr Gerät"
#frame to select a plan to subscribe
plan_subscribe:
subscribe_online: "online abonnieren"
do_not_subscribe: "nicht abonnieren"
#admin: choose a member to interact with
member_select:
select_a_member: "Ein Mitglied auswählen"
start_typing: "Tippe ein..."
#stripe payment modal
stripe:
online_payment: "Online-Bezahlung"
i_have_read_and_accept_: "Ich habe gelesen und akzeptiere"
_the_general_terms_and_conditions: "die allgemeinen Nutzungs- und Geschäftsbedingungen."
credit_amount_for_pay_reservation: "{amount} {currency} muss noch bezahlt werden, um Ihre Reservierung zu bestätigen"
client_credit_amount_for_pay_reservation: "{amount} {currency} muss noch bezahlt werden, um die Reservierung des Kunden zu bestätigen"
confirm_payment_of_: "Bezahlen: {AMOUNT}"
#dialog of on site payment for reservations
valid_reservation_modal:
booking_confirmation: "Buchungsbestätigung"
here_is_the_summary_of_the_slots_to_book_for_the_current_user: "Hier ist die Zusammenfassung der zu buchenden Slots für den aktuellen Benutzer:"
#event edition form
event:
title: "Titel"
title_is_required: "Titel ist erforderlich."
matching_visual: "Passendes Bild"
choose_a_picture: "Bild auswählen"
description: "Beschreibung"
description_is_required: "Beschreibung ist erforderlich."
attachments: "Dateianhänge"
add_a_new_file: "Neue Datei hinzufügen"
event_type: "Art der Veranstaltung"
dates_and_opening_hours: "Termine und Öffnungszeiten"
all_day: "Ganztägig"
start_date: "Startdatum"
end_date: "Enddatum"
start_time: "Startzeit"
end_time: "Ende"
recurrence: "Wiederholung"
_and_ends_on: "und endet am"
prices_and_availabilities: "Preise und Verfügbarkeiten"
standard_rate: "Standardpreis"
0_equal_free: "0 = kostenlos"
tickets_available: "Tickets verfügbar"
event_theme: "Veranstaltungsthema"
age_range: "Altersklasse"
#subscription plan edition form
plan:
general_information: "Allgemeine Informationen"
name: "Name"
name_is_required: "Name ist erforderlich"
name_length_must_be_less_than_24_characters: "Der Name muss weniger als 24 Zeichen lang sein."
type: "Typ"
partner: "Partner"
standard: "Standard"
type_is_required: "Typ ist erforderlich."
group: "Gruppe"
groups: "Gruppen"
all: "Alle"
transversal_all_groups: "Transversal (alle Gruppen)"
group_is_required: "Gruppe ist erforderlich."
number_of_periods: "Anzahl der Zeiträume"
number_of_periods_is_required: "Anzahl der Zeiträume ist erforderlich."
period: "Zeitraum"
year: "Jahr"
month: "Monat"
week: "Woche"
period_is_required: "Zeitraum ist erforderlich."
subscription_price: "Abonnementspreis"
price_is_required: "Preis ist erforderlich."
visual_prominence_of_the_subscription: "Sichtbarkeit des Abonnements"
on_the_subscriptions_page_the_most_prominent_subscriptions_will_be_placed_at_the_top_of_the_list: "Auf der Abonnement-Seite werden die prominentesten Abonnements ganz oben auf der Liste platziert."
an_evelated_number_means_a_higher_prominence: "Eine höhere Zahl bedeutet einen höheren Stellenwert."
rolling_subscription: "Rollendes Abonnement?"
a_rolling_subscription_will_begin_the_day_of_the_first_training: "Ein rollendes Abonnement beginnt mit dem Tag der ersten Schulung."
otherwise_it_will_begin_as_soon_as_it_is_bought: "Andernfalls beginnt es ab Kaufdatum."
information_sheet: "Informationsblatt"
attach_an_information_sheet: "Ein Informationsblatt anhängen"
notified_partner: "Benachrichtigter Partner"
new_user: "Neuer Nutzer..."
as_part_of_a_partner_subscription_some_notifications_may_be_sent_to_this_user: "Als Teil eines Partnerabonnements können einige Benachrichtigungen an diesen Benutzer gesendet werden."
new_partner: "Neuer Partner"
first_name: "Vorname"
first_name_is_required: "Der Vorname ist erforderlich."
surname: "Nachname"
surname_is_required: "Der Nachname ist erforderlich."
email_address: "EMailAdresse"
email_address_is_required: "Die E-Mail-Adresse ist erforderlich."
disabled: "Abonnement deaktivieren"
disable_plan_will_not_unsubscribe_users: "Achtung: Das Deaktivieren dieses Pakets wird Benutzer mit aktiven Abonnements nicht abbestellen."
#training edition form
trainings:
name: "Name"
name_is_required: "Name ist erforderlich."
illustration: "Abbildung"
add_an_illustration: "Bild hinzufügen"
description: "Beschreibung"
description_is_required: "Beschreibung ist erforderlich."
add_a_new_training: "Neue Schulung hinzufügen"
validate_your_training: "Schulung bestätigen"
associated_machines: "Verknüpfte Maschinen"
number_of_tickets: "Anzahl der Tickets"
public_page: "In Schulungslisten anzeigen"
disable_training: "Training deaktivieren"
#partial form to edit/create an user (admin view)
user_admin:
user: "Nutzer"
incomplete_profile: "Unvollständiges Profil"
user_profile: "Nutzerprofil"
warning_incomplete_user_profile_probably_imported_from_sso: "Warnung: Das Profil dieses Benutzers ist unvollständig. Da \"Single Sign-on\" (SSO) Authentifizierung derzeit aktiviert ist, kann es sich wahrscheinlich um ein importiertes, aber nicht zusammengeführtes Konto handeln. Ändern Sie es nicht, es sei denn, Sie wissen, was Sie tun."
group: "Gruppe"
group_is_required: "Gruppe ist erforderlich."
trainings: "Schulungen"
tags: "Stichwörter"
#partial form to edit/create an authentication provider (SSO)
authentication:
name: "Name"
provider_name_is_required: "Sie müssen einen Providernamen eingeben."
authentication_type: "Authentifizierungsart"
local_database: "Lokale Datenbank"
o_auth2: "OAuth 2.0"
authentication_type_is_required: "Authentifizierungstyp ist erforderlich."
data_mapping: "Datenzuordnung"
expected_data_type: "Erwarteter Datentyp"
input_format: "Eingabeformat"
mappings: "Zuordnungen"
#edition/creation form of an OAuth2 authentication provider
oauth2:
common_url: "Gemeinsame URL"
common_url_is_required: "Gemeinsame URL ist erforderlich."
provided_url_is_not_a_valid_url: "Die angegebene URL ist keine gültige URL."
authorization_endpoint: "Authentifizierungs-Endpunkt"
oauth2_authorization_endpoint_is_required: "OAuth 2.0 Autorisierungs-Endpunkt ist erforderlich."
provided_endpoint_is_not_valid: "Angegebener Endpunkt ist ungültig."
token_acquisition_endpoint: "Endpunkt der Token-Akquisition"
oauth2_token_acquisition_endpoint_is_required: "Endpunkt des OAuth 2.0-Tokens ist erforderlich."
profil_edition_url: "Profil-Editierungs-URL"
profile_edition_url_is_required: "URL zur Profil-Editierung ist erforderlich."
client_identifier: "Client-Identifier"
oauth2_client_identifier_is_required: "OAuth 2.0 Client-Identifier ist erforderlich."
obtain_it_when_registering_with_your_provider: "Wird während der Registrierung bei Ihrem Provider erhalten."
client_secret: "Client-Geheimnis"
oauth2_client_secret_is_required: "OAuth 2.0 Client-Geheimnis ist erforderlich."
define_the_fields_mapping: "Definieren Sie die Zuordnung der Felder"
add_a_match: "Fügen Sie eine Zuordnung hinzu"
model: "Modell"
field: "Felder"
api_endpoint_url: "URL des API-Endpunkts"
api_type: "API-Typ"
api_fields: "API-Felder"
#machine/training slot modification modal
confirm_modify_slot_modal:
change_the_slot: "Slot ändern"
do_you_want_to_change_your_booking_slot_initially_planned_at: "Möchten Sie Ihren Buchungsslot ändern? Ursprünglich geplant um:"
do_you_want_to_change_NAME_s_booking_slot_initially_planned_at: "Möchten Sie den {NAME}-Buchungsplatz ändern? Ursprünglich geplant um:"
cancel_this_reservation: "Reservierung stornieren"
i_want_to_change_date: "Ich möchte das Datum ändern"
#modal introducing that a training is requested before booking a machine
request_training_modal:
to_book_the_MACHINE_you_must_have_completed_the_TRAINING: "Um \"{MACHINE}\" zu buchen, müssen Sie {TRAINING} abgeschlossen haben."
register_for_the_training: "Zur Schulung anmelden"
i_dont_want_to_register_now: "Ich möchte mich jetzt nicht anmelden"
#modal introducing that a user must wait for his training being validated before booking a machine
training_reservation_modal:
machine_reservation: "Maschinenreservierung"
you_must_wait_for_your_training_is_being_validated_by_the_fablab_team_to_book_this_machine: "Sie müssen bis zur Schulungsbestätigung warten, um diese Maschine buchen zu können."
your_training_will_occur_: "Ihre Schulung wird stattfinden"
#user public profile
public_profile:
last_activity_html: "Letzte Aktivität <br><strong>am {DATE}</strong>"
to_come: "kommend"
approved: "bestätigt"
projects: "Projekte"
no_projects: "Keine Projekte"
author: "Autor"
collaborator: "Mitarbeitende"
private_profile: "Privates Profil"
interests: "Interessen"
CAD_softwares_mastered: "Kenntnisse in CAD-Software"
email_address: "EMailAdresse"
trainings: "Schulungen"
no_trainings: "Keine Schulungen"
#wallet
wallet:
wallet: 'Guthabenkonto'
your_wallet_amount: 'verfügbares Guthaben'
wallet_amount: 'Verfügbares Guthaben'
no_transactions_for_now: 'Momentan keine Transaktionen'
date: "Datum"
operation: 'Vorgang'
operator: 'Operator'
amount: 'Betrag'
credit: 'Guthaben'
debit: 'Lastschrift'
credit_title: 'Guthabenkonto'
credit_label: 'Legen Sie den Betrag der Gutschrift fest'
confirm_credit_label: 'Bestätigen Sie den Betrag der Gutschrift'
generate_a_refund_invoice: "Erstelle eine Rückerstattungs-Rechnung"
creation_date_for_the_refund: "Erstellungsdatum für die Erstattung"
creation_date_is_required: "Erstellungsdatum ist erforderlich."
description_optional: "Beschreibung (optional):"
will_appear_on_the_refund_invoice: "Wird auf der Rückerstattungsrechnung angezeigt."
to_credit: 'Guthaben'
wallet_credit_successfully: "Gutschrift wurde erfolgreich dem Guthaben des Benutzers gutgeschrieben."
a_problem_occurred_for_wallet_credit: "Ein Problem ist aufgetreten, als dem Benutzer die Gutschrift gutgeschrieben wurde."
amount_is_required: "Betrag ist erforderlich."
amount_minimum_1: "Der Mindestbetrag ist 1"
amount_confirm_is_required: "Die Bestätigung des Betrags ist erforderlich."
amount_confirm_does_not_match: "Betrag und Betragsbestätigung stimmen nicht überein."
you_have_amount_in_wallet: "Ihr Gutgaben beträgt {amount} {currency}"
client_have_amount_in_wallet: "Das guthaben des Kunden beträgt {amount} {currency}"
wallet_pay_reservation: "Sie können Ihre Reservierung direkt bezahlen"
client_wallet_pay_reservation: "Das Mitglied kann seine Reservierung direkt bezahlen"
debit_subscription: "Bezahlen für ein Abonnement"
debit_reservation_training: "Für eine Schulungsreservierung bezahlen"
debit_reservation_machine: "Für eine Maschinenreservierung bezahlen"
debit_reservation_event: "Für eine Veranstaltungsreservierung bezahlen"
warning_uneditable_credit: "Warnung: Nach der Bestätigung kann der gutgeschriebene Betrag nicht mehr bearbeitet werden."
#promotional coupon (creation/edition form)
coupon:
name: "Name"
name_is_required: "Name ist erforderlich."
code: "Code"
code_is_required: "Code ist erforderlich."
code_must_be_composed_of_capital_letters_digits_and_or_dashes: "Der Code muss aus Großbuchstaben, Ziffern und/oder Bindestrichen bestehen."
kind_of_coupon: "Art des Gutscheins"
percentage: "Prozentsatz"
amount: "Betrag"
amount_off: "Vergünstigter Betrag"
percent_off: "Vergünstigter Prozentsatz"
percent_off_is_required: "Vergünstigter Prozentsatz ist erforderlich."
percentage_must_be_between_0_and_100: "Prozentsatz muss zwischen 0 und 100 liegen."
validity_per_user: "Gültigkeit pro Benutzer"
once: "Nur einmal"
forever: "Jede Nutzung"
validity_per_user_is_required: "Validität pro Benutzer ist erforderlich."
valid_until: "Gültig bis (inklusive)"
leave_empty_for_no_limit: "Geben Sie keine Befristung an, indem Sie das Feld leer lassen."
max_usages: "Maximal zulässige Nutzungen"
max_usages_must_be_equal_or_greater_than_0: "Die Zahl der maximal zulässigen Verwendungen muss größer als 0 sein."
enabled: "Aktiv"
#coupon (input zone for users)
coupon_input:
i_have_a_coupon: "Ich habe einen Gutschein!"
code_: "Code:"
the_coupon_has_been_applied_you_get_PERCENT_discount: "Der Gutschein wurde angewendet. Sie erhalten einen Rabatt von {PERCENT}%."
the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY: "Der Gutschein wurde angewendet. Sie erhalten einen Rabatt von {AMOUNT} {CURRENCY}."
unable_to_apply_the_coupon_because_disabled: "Der Gutschein konnte nicht angewendet werden: Dieser Code wurde deaktiviert."
unable_to_apply_the_coupon_because_expired: "Der Gutschein konnte nicht angewendet werden: Dieser Code ist abgelaufen."
unable_to_apply_the_coupon_because_sold_out: "Der Gutschein kann nicht angewendet werden: Dieser Code hat sein Kontingent erreicht."
unable_to_apply_the_coupon_because_already_used: "Der Gutschein konnte nicht angewendet werden: Sie haben diesen Code bereits einmal verwendet."
unable_to_apply_the_coupon_because_amount_exceeded: "Der Gutschein kann nicht eingelöst werden: Der Rabatt überschreitet den Gesamtbetrag dieses Kaufs."
unable_to_apply_the_coupon_because_undefined: "Der Gutschein konnte nicht eingelöst werden: Ein unerwarteter Fehler ist aufgetreten, bitte kontaktieren Sie den Fablab-Manager."
unable_to_apply_the_coupon_because_rejected: "Dieser Code existiert nicht."
#form to create/edit a space
space:
name: "Name"
name_is_required: "Name ist erforderlich."
illustration: "Abbildung"
add_an_illustration: "Abbildung hinzufügen"
description: "Beschreibung"
description_is_required: "Beschreibung ist erforderlich."
characteristics: "Eigenschaften"
characteristics_are_required: "Eigenschaften sind erforderlich."
attached_files_pdf: "Dateianhänge (pdf)"
attach_a_file: "Datei anhängen"
add_an_attachment: "Anhang hinzufügen"
default_places: "Maximale Anzahl von Tickets"
default_places_is_required: "Maximale Anzahl an Tickets ist erforderlich."
disable_space: "Raum deaktivieren"
#shopping cart module for reservations
cart:
summary: "Zusammenfassung"
select_one_or_more_slots_in_the_calendar: "Wähle einen {SINGLE, select, true{Slot} other{oder mehrere Slots}} im Kalender"
you_ve_just_selected_the_slot: "Sie haben gerade den Slot ausgewählt:"
datetime_to_time: "{START_DATETIME} bis {END_TIME}" #eg: Thursday, September 4 1986 8:30 PM to 10:00 PM
cost_of_TYPE: "Kosten für den {TYPE, select, Machine{Maschinenslot} Training{Schulungsslot} Space{Raum-Slot} other{anderes Element}}"
offer_this_slot: "Diesen Slot anbieten"
confirm_this_slot: "Diesen Slot bestätigen"
remove_this_slot: "Diesen Slot entfernen"
to_benefit_from_attractive_prices: "Um von günstigen Ageboten zu profitieren"
view_our_subscriptions: "Lassen Sie sich unsere Abonnements vorstellen"
or: "oder"
you_ve_just_selected_a_: "Sie wählten gerade ein"
_subscription: "Abonnement"
cost_of_the_subscription: "Kosten des Abonnements"
confirm_and_pay: "Bestätigen und bezahlen"
you_have_settled_the_following_TYPE: "Sie haben die folgenden {TYPE, select, Machine{Maschinenslots} Training{Schulungen} other{Elemente}} beglichen:"
you_have_settled_a_: "Sie haben beglichen"
total_: "GESAMT :"
thank_you_your_payment_has_been_successfully_registered: "Vielen Dank. Ihre Zahlung wurde erfolgreich registriert!"
your_invoice_will_be_available_soon_from_your_: "Ihre Rechnung wird in Kürze verfügbar sein via"
dashboard: "Dashboard"
i_want_to_change_the_following_reservation: "Ich möchte folgende Reservierung ändern:"
cancel_my_modification: "Änderung abbrechen"
select_a_new_slot_in_the_calendar: "Wählen Sie einen neuen Slot im Kalender"
cancel_my_selection: "Auswahl aufheben"
tags_of_the_original_slot: "Tags des ursprünglichen Slots:"
tags_of_the_destination_slot: "Tags des Ziel-Slots:"
confirm_my_modification: "Meine Änderung bestätigen"
your_booking_slot_was_successfully_moved_from_: "Ihr Buchungs-Slot wurde erfolgreich verschoben von"
to_date: "zu" #eg. from 01/01 to 01/05
please_select_a_member_first: "Bitte wählen Sie zuerst ein Mitglied"
unable_to_select_plan_if_slots_in_the_past: "Es kann kein Plan ausgewählt werden, wenn einer der ausgewählten Slots in der Vergangenheit liegt"
unable_to_change_the_reservation: "Die Reservierung konnte nicht geändert werden"
confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_cancel_this_reservation_html: "<p>Möchten Sie diese Reservierung wirklich stornieren?</p><p>Achtung: wenn diese Reservierung kostenlos, als Teil eines Abonnements erfolgt, wird das aufgewendete Guthaben nicht zurückerstattet.</p>"
reservation_was_cancelled_successfully: "Die Reservierung wurde erfolgreich storniert."
cancellation_failed: "Stornierung fehlgeschlagen."
confirm_payment_of_html: "{ROLE, select, admin{Bezahlung vor Ort} other{Bezahlen}}: {AMOUNT}" #eg. confirm my payment of $20.00
a_problem_occurred_during_the_payment_process_please_try_again_later: "Während des Zahlungsvorgangs ist ein Problem aufgetreten. Bitte versuchen Sie es später erneut."
none: "Keine"
online_payment_disabled: "Online-Zahlung ist nicht verfügbar. Bitte kontaktieren Sie die FabLab-Rezeption direkt."
slot_restrict_plans: "Dieser Slot ist auf die folgenden Pläne beschränkt:"
slot_restrict_subscriptions_must_select_plan: "Der Slot ist nur für Abonnenten verfügbar. Bitte wählen Sie zuerst einen Plan aus."
slot_restrict_plans_of_others_groups: "Der Slot ist für die Abonnenten anderer Gruppen beschränkt."
selected_plan_dont_match_slot: "Ausgewählter Plan stimmt nicht mit diesem Slot überein"
user_plan_dont_match_slot: "Vom Nutzer abonnierter Plan stimmt nicht mit diesem Slot überein"
no_plan_match_slot: "Sie haben keinen passenden Plan für diesen Slot"
slot_at_same_time: "Konflikt mit anderen Reservierungen"
do_you_really_want_to_book_slot_at_same_time: "Wollen Sie wirklich diesen Slot buchen? Andere Buchungen finden zur gleichen Zeit statt"
unable_to_book_slot_because_really_have_reservation_at_same_time: "Dieser Slot kann nicht gebucht werden, da die folgende Reservierung zur gleichen Zeit erfolgt."
tags_mismatch: "Tags stimmen nicht überein"
confirm_book_slot_tags_mismatch: "Wollen Sie wirklich diesen Slot buchen? {USER} hat keine der erforderlichen Tags."
unable_to_book_slot_tags_mismatch: "Dieser Slot kann nicht gebucht werden, da Sie keine der benötigten Tags haben."
slot_tags: "Slot-Tags"
user_tags: "Nutzer-Tags"
no_tags: "Keine Tags"
#feature-tour modal
tour:
previous: "Vorherige"
next: "Nächste"
end: "Tour beenden"
#help modal
help:
title: "Hilfe"
what_to_do: "Was möchten Sie tun?"
tour: "Funktionstour starten"
guide: "Benutzerhandbuch öffnen"

View File

@ -359,6 +359,8 @@ en:
validity_per_user: "Validity per user"
once: "Just once"
forever: "Each use"
warn_validity_once: "Please note that when this coupon will be used with a payment schedule, the discount will be applied to the first deadline only."
warn_validity_forever: "Please note that when this coupon will be used with a payment schedule, the discount will be applied to each deadlines."
validity_per_user_is_required: "Validity per user is required."
valid_until: "Valid until (included)"
leave_empty_for_no_limit: "Do not specify any limit by leaving the field empty."
@ -371,6 +373,7 @@ en:
code_: "Code:"
the_coupon_has_been_applied_you_get_PERCENT_discount: "The coupon has been applied. You get a {PERCENT}% discount."
the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY: "The coupon has been applied. You get a discount of {AMOUNT} {CURRENCY}."
coupon_validity_once: "This coupon is valid only once. In case of payment schedule, only for the first deadline."
unable_to_apply_the_coupon_because_disabled: "Unable to apply the coupon: this code was disabled."
unable_to_apply_the_coupon_because_expired: "Unable to apply the coupon: this code has expired."
unable_to_apply_the_coupon_because_sold_out: "Unable to apply the coupon: this code reached its quota."

View File

@ -359,6 +359,8 @@ fr:
validity_per_user: "Validité par utilisateur"
once: "Une seule fois"
forever: "À chaque utilisation"
warn_validity_once: "Veuillez noter que lors de l'utilisation de ce code promo avec un échéancier de paiement, la réduction sera appliquée uniquement à la première échéance."
warn_validity_forever: "Veuillez noter que lors de l'utilisation de ce code promo avec un échéancier de paiement, la réduction sera appliquée à chaque échéance."
validity_per_user_is_required: "La validité par utilisateur est requise."
valid_until: "Valable jusqu'au (inclus)"
leave_empty_for_no_limit: "Laissez vide pour ne pas spécifier de limite."
@ -371,6 +373,7 @@ fr:
code_: "Code :"
the_coupon_has_been_applied_you_get_PERCENT_discount: "Le code promo a bien été appliqué. Vous bénéficiez d'une remise de {PERCENT} %."
the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY: "Le code promo a bien été appliqué. Vous bénéficiez d'une remise de {AMOUNT} {CURRENCY}."
coupon_validity_once: "Ce code promo n'est valide qu'une seule fois. En cas de paiement échelonné, seulement pour la première échéance."
unable_to_apply_the_coupon_because_disabled: "Impossible d'appliquer la réduction : ce code promo a été désactivé."
unable_to_apply_the_coupon_because_expired: "Impossible d'appliquer la réduction : ce code promo a expiré."
unable_to_apply_the_coupon_because_sold_out: "Impossible d'appliquer la réduction : ce code promo a atteint son quota."

397
config/locales/de.yml Normal file
View File

@ -0,0 +1,397 @@
de:
#subscription plan duration
duration:
year:
one: 'ein Jahr'
other: '%{count} Jahre'
month:
one: 'Ein Monat'
other: '%{count} Monate'
week:
one: 'Eine Woche'
other: '%{count} Wochen'
errors:
#CarrierWave
messages:
carrierwave_processing_error: "konnte nicht verarbeitet werden"
carrierwave_integrity_error: "ist kein erlaubter Dateityp"
carrierwave_download_error: "konnte nicht heruntergeladen werden"
extension_whitelist_error: "Sie sind nicht berechtigt, %{extension} Dateien hochzuladen, erlaubt sind die Typen: %{allowed_types}"
extension_blacklist_error: "Sie sind nicht berechtigt, %{extension} Dateien hochzuladen. Unerlaubte Typen: %{prohibited_types}"
content_type_whitelist_error: "Sie sind nicht berechtigt, %{content_type} Dateien hochzuladen, erlaubt sind die Typen: %{allowed_types}"
rmagick_processing_error: "Fehler beim Bearbeiten mit rmagick, vielleicht ist es kein Bild? Original Fehler: %{e}"
mime_types_processing_error: "Fehler beim Verarbeiten der Datei mit MIME::Typen, möglicherweise kein gültiger Inhaltstyp? Original Fehler: %{e}"
mini_magick_processing_error: "Fehler beim Bearbeiten mit MiniMagick, vielleicht ist es kein Bild? Original Fehler: %{e}"
wrong_size: "hat die falsche Größe (sollte %{file_size} sein)"
size_too_small: "ist zu klein (sollte mindestens %{file_size} sein)"
size_too_big: "ist zu groß (sollte höchstens %{file_size} sein)"
export_not_found: "Der angeforderte Export wurde nicht gefunden. Wahrscheinlich wurde er gelöscht. Bitte erstellen Sie einen neuen Export."
percentage_out_of_range: "Prozentwert muss zwischen 0 und 100 liegen"
cannot_be_blank_at_same_time: "darf nicht leer sein, wenn %{field} auch leer ist"
cannot_be_in_the_past: "darf nicht in der Vergangenheit liegen"
cannot_be_before_previous_value: "darf nicht vor dem vorherigen Wert liegen"
cannot_overlap: "darf einen bestehenden Abrechnungszeitraum nicht überlappen"
cannot_encompass: "darf einen bestehenden Abrechnungszeitraum nicht umfassen"
in_closed_period: "darf nicht innerhalb eines geschlossenen Abrechnungszeitraums sein"
invalid_footprint: "die Prüfsumme der Rechnung ist ungültig"
end_before_start: "Das Enddatum darf nicht vor dem Startdatum liegen. Wählen Sie ein Datum nach %{START}"
invalid_duration: "Der zulässige Zeitraum muss zwischen 1 Tag und 1 Jahr lang sein. Ihr Zeitraum ist %{DAYS} Tage lang."
must_be_in_the_past: "Der Zeitraum darf ausschließlich vor dem heutigen Datum liegen."
apipie:
api_documentation: "API-Dokumentation"
code: "HTTP code"
#error messages when importing an account from a SSO
omniauth:
email_already_linked_to_another_account_please_input_your_authentication_code: "E-Mail-Adresse \"%{OLD_MAIL}\" ist bereits mit einem Konto verknüpft. Bitte geben Sie Ihren Authentifizierungscode ein."
your_username_is_already_linked_to_another_account_unable_to_update_it: "Ihr Benutzername (%{USERNAME}) ist bereits einem anderen Konto zugeordnet. Aktualisierung nicht möglich."
your_email_address_is_already_linked_to_another_account_unable_to_update_it: "Ihre E-Mail-Adresse (%{EMAIL}) ist bereits einem anderen Konto zugeordnet. Aktualisierung nicht möglich."
this_account_is_already_linked_to_an_user_of_the_platform: "Das Konto %{NAME} wird bereits von einem Benutzer der Plattform verwendet."
#availability slots in the calendar
availabilities:
not_available: "Nicht verfügbar"
i_ve_reserved: "Ich reservierte"
length_must_be_slot_multiple: "muss mindestens %{MIN} Minuten nach dem Startdatum liegen"
must_be_associated_with_at_least_1_machine: "muss mindestens einer Maschine zugeordnet sein"
#members management
members:
unable_to_change_the_group_while_a_subscription_is_running: "Die Gruppe kann während eines Abonnements nicht geändert werden"
admins_cant_change_group: "Ein Administrator kann nicht aus seiner eigenen Gruppe entfernt werden"
please_input_the_authentication_code_sent_to_the_address: "Bitte geben Sie den Authentifizierungscode ein, der an die E-Mail-Adresse %{EMAIL} gesendet wurde"
your_authentication_code_is_not_valid: "Der Authentifizierungscode ist ungültig."
current_authentication_method_no_code: "Die aktuelle Authentifizierungsmethode erfordert keinen Migrationscode"
requested_account_does_not_exists: "Das gewünschte Konto ist nicht vorhanden"
#PDF invoices generation
invoices:
refund_invoice_reference: "Beleg der Rechnungsrückerstattungung: %{REF}"
invoice_reference: "Rechnungsbezug: %{REF}"
code: "Code: %{CODE}"
order_number: "Bestellnummer: %{NUMBER}"
invoice_issued_on_DATE: "Rechnung ausgestellt am %{DATE}"
refund_invoice_issued_on_DATE: "Rückerstattungsrechnung ausgestellt am %{DATE}"
wallet_credit: "Vorhandenes Guthaben"
cancellation_of_invoice_REF: "Stornierung der Rechnung %{REF}"
reservation_of_USER_on_DATE_at_TIME: "Reservierung von %{USER} am %{DATE} um %{TIME}"
cancellation: "Stornierung"
object: "Gegenstand:"
order_summary: "Bestellübersicht:"
details: "Details"
amount: "Betrag"
subscription_extended_for_free_from_START_to_END: "Kostenlose Abonnementverlängerung - von %{START} bis %{END}"
subscription_NAME_from_START_to_END: "Abonnement %{NAME} - Von %{START} bis %{END}"
machine_reservation_DESCRIPTION: "Maschinen-Reservierung - %{DESCRIPTION}"
space_reservation_DESCRIPTION: "Raumreservierung - %{DESCRIPTION}"
training_reservation_DESCRIPTION: "Trainingsreservierung - %{DESCRIPTION}"
event_reservation_DESCRIPTION: "Veranstaltungs-Reservierung - %{DESCRIPTION}"
full_price_ticket:
one: "Ein Vollpreis-Ticket"
other: "%{count} Vollpreis-Tickets"
other_rate_ticket:
one: "Ein %{NAME}-Ticket"
other: "%{count} %{NAME}-Tickets"
reservation_other: "Reservierung (andere)"
coupon_CODE_discount_of_DISCOUNT: "Gutschein {CODE}: Rabatt von {DISCOUNT}{TYPE, select, percent_off{%} other{}}" #messageFormat interpolation
total_including_all_taxes: "Gesamtpreis inkl. Steuern"
including_VAT_RATE: "Inklusive MwSt. %{RATE}%"
including_total_excluding_taxes: "Gesamtbetrag zzgl. Steuern"
including_amount_payed_on_ordering: "Inklusive bei Bestellung bezahlter Betrag"
total_amount: "Gesamtbetrag"
refund_on_DATE: "Erstattung am %{DATE}"
by_stripe_online_payment: "via Stripe (Online-Zahlung)"
by_cheque: "per Scheck"
by_transfer: "per Banküberweisung"
by_cash: "in bar"
by_wallet: "durch Guthaben"
no_refund: "Keine Rückerstattung"
settlement_by_debit_card: "Abrechnung per Debitkarte"
settlement_done_at_the_reception: "Abrechnung an der Rezeption durchgeführt"
settlement_by_wallet: "Abrechnung per Guthaben"
on_DATE_at_TIME: "am %{DATE} um %{TIME},"
for_an_amount_of_AMOUNT: "für einen Betrag von %{AMOUNT}"
on_DATE_from_START_to_END: "Am %{DATE} von %{START} bis %{END}" #eg: on feb. 7 from 7AM to 9AM
from_STARTDATE_to_ENDDATE_from_STARTTIME_to_ENDTIME: "Von %{STARTDATE} bis %{ENDDATE}, von %{STARTTIME} bis %{ENDTIME}" #eg: from feb. 7 to feb. 10, from 6PM to 10PM
subscription_of_NAME_for_DURATION_starting_from_DATE: "Abonnement von %{NAME} für %{DURATION} ab %{DATE}"
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Abonnement von %{NAME} verlängert (kostenlose Tage) ab %{STARTDATE} bis %{ENDDATE}"
and: 'und'
invoice_text_example: "Unsere Einrichtung ist nicht mehrwertsteuerpflichtig"
#CVS accounting export (columns headers)
accounting_export:
journal_code: "Journalcode"
date: "Eintragsdatum"
account_code: "Code des Kontos"
account_label: "Kontobezeichnung"
piece: "Dokument"
line_label: "Eintragsbezeichnung"
debit_origin: "Ursprungssoll"
credit_origin: "Ursprungsguthaben"
debit_euro: "Soll in Euro"
credit_euro: "Guthaben in Euro"
lettering: "Beschriftung"
VAT: 'Mwst.'
subscription: "Abonnement"
Machine_reservation: "Maschinenreservierung"
Training_reservation: "Schulungsreservierung"
Event_reservation: "Veranstaltungsreservierung"
Space_reservation: "Raumreservierung"
wallet: "Guthabenkonto"
#training availabilities
trainings:
i_ve_reserved: "Ich reservierte"
completed: "Vollständig"
#error messages when updating an event
events:
error_deleting_reserved_price: "Der angeforderte Preis konnte nicht gelöscht werden, da er mit einigen Reservierungen verknüpft ist"
other_error: "Unerwarteter Fehler beim Aktualisieren der Veranstaltung"
#event duration
from_STARTDATE_to_ENDDATE: "Von %{STARTDATE} bis %{ENDDATE},"
from_STARTTIME_to_ENDTIME: "von %{STARTTIME} bis %{ENDTIME}"
#members list export to EXCEL format
export_members:
members: "Mitglieder"
id: "ID"
surname: "Nachname"
first_name: "Vorname"
email: "E-Mail"
newsletter: "Newsletter"
last_login: "Letzte Anmeldung"
gender: "Geschlecht"
age: "Alter"
address: "Adresse"
phone: "Telefon"
website: "Webseite"
job: "Aufgabe"
interests: "Interessen"
cad_software_mastered: "CAD-Software gemeistert"
group: "Gruppe"
subscription: "Abonnement"
subscription_end_date: "Enddatum des Abonnements"
validated_trainings: "Validierte Schulungen"
tags: "Stichworte"
number_of_invoices: "Anzahl der Rechnungen"
projects: "Projekte"
facebook: "Facebook"
twitter: "Twitter"
echo_sciences: "Echosciences"
organization: "Organisation"
organization_address: "Adresse der Organisation"
man: "Mann"
woman: "Frau"
without_subscriptions: "Ohne Abonnement"
#machines/trainings/events reservations list to EXCEL format
export_reservations:
reservations: "Reservierungen"
customer_id: "Kunden ID"
customer: "Kunde"
email: "E-Mail"
reservation_date: "Reservierungsdatum"
reservation_type: "Reservierungsart"
reservation_object: "Gegenstand der Reservierung"
slots_number_hours_tickets: "Anzahl Slots (Stunden/Tickets)"
payment_method: "Zahlungsmethode"
local_payment: "Zahlung an der Rezeption"
online_payment: "Online-Zahlung"
deleted_user: "Gelöschter Nutzer"
#subscriptions list export to EXCEL format
export_subscriptions:
subscriptions: "Abonnements"
id: "ID"
customer: "Kunde"
email: "E-Mail"
subscription: "Abonnement"
period: "Zeitraum"
start_date: "Startdatum"
expiration_date: "Ablaufdatum"
amount: "Betrag"
payment_method: "Zahlungsmethode"
local_payment: "Zahlung an der Rezeption"
online_payment: "Online-Zahlung"
deleted_user: "Gelöschter Nutzer"
#reservation slots export, by type, to EXCEL format
export_availabilities:
machines: "Maschinen"
trainings: "Schulungen"
spaces: "Räume"
events: "Veranstaltungen"
day_of_week: "Wochentag"
date: "Datum"
slot: "Slot"
machine: "Maschine"
training: "Schulung"
space: "Raum"
event: "Veranstaltung"
reservations: "Reservierungen"
available_seats: "Verfügbare Plätze"
roles:
member: "Mitglied"
manager: "Manager"
admin: "Administrator"
api:
#internal app notifications
notifications:
deleted_user: "Gelöschter Nutzer"
notify_admin_abuse_reported:
an_abuse_was_reported_on_TYPE_ID_NAME_html: "Ein Missbrauchsmeldung auf <strong>%{TYPE} %{ID} ist eingegangen: <em>%{NAME}</em></strong>."
notify_admin_member_create_reservation:
a_RESERVABLE_reservation_was_made_by_USER_html: "Eine <strong><em>%{RESERVABLE}</em></strong> Reservierung wurde von <strong><em>%{USER}</em></strong> vorgenommen."
notify_admin_profile_complete:
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Konto importiert von <strong><em>%{PROVIDER}</strong> (%{UID})</em> hat seine Informationen vervollständigt."
notify_admin_slot_is_canceled:
USER_s_reservation_on_the_DATE_was_cancelled_remember_to_generate_a_refund_invoice_if_applicable_html: "Die Reservierung von <strong><em>%{USER}</em></strong> am %{DATE} wurde storniert. Erstellen Sie eine Rückerstattung, falls zutreffend."
notify_admin_slot_is_modified:
a_booking_slot_was_modified: "Ein Buchungsplatz wurde geändert."
notify_admin_subscribed_plan:
subscription_PLAN_has_been_subscribed_by_USER_html: "Das Abonnement <strong><em>%{PLAN}</em></strong> wurde von <strong><em>%{USER}</strong></em> abgeschlossen."
notify_admin_subscription_canceled:
USER_s_subscription_has_been_cancelled: "Das Abonnement von %{USER} wurde gekündigt."
notify_admin_subscription_extended:
subscription_PLAN_of_the_member_USER_has_been_extended_FREE_until_DATE_html: "Das Abonnement <strong><em>{PLAN}</em></strong> des Mitglieds <strong><em>{USER}</strong></em> wurde verlängert {FREE, select, true{kostenlos} other{}} bis {DATE}." #messageFormat interpolation
notify_admin_subscription_is_expired:
USER_s_subscription_has_expired: "Das Abonnement von %{USER} ist abgelaufen."
notify_admin_subscription_will_expire_in_7_days:
USER_s_subscription_will_expire_in_7_days: "Das Abonnement von %{USER} wird in 7 Tagen ablaufen."
notify_admin_user_group_changed:
user_NAME_changed_his_group_html: "Benutzer <strong><em>{NAME}</strong></em> hat {GENDER, select, true{seine} other{ihre}} Gruppe geändert." #messageFormat interpolation
notify_admin_user_merged:
user_NAME_has_merged_his_account_with_the_one_imported_from_PROVIDER_UID_html: "Nutzer <strong><em>{NAME}</strong></em> hat {GENDER, select, true{seinen} other{ihren}} Account mit dem von <strong><em>{PROVIDER} </strong> ({UID})</em> importierten Account zusammengeführt." #messageFormat interpolation
notify_admin_when_project_published:
project_NAME_has_been_published_html: "Projekt <a href='/#!/projects/%{ID}'><strong><em>%{NAME}<em></strong></a> wurde veröffentlicht."
notify_admin_when_user_is_created:
a_new_user_account_has_been_created_NAME_EMAIL_html: "Ein neues Benutzerkonto wurde erstellt: <strong><em>%{NAME} &lt;%{EMAIL}&gt;</strong></em>."
notify_admin_when_user_is_imported:
a_new_user_account_has_been_imported_from_PROVIDER_UID_html: "Ein neues Benutzerkonto wurde von <strong><em>%{PROVIDER}</strong> (%{UID})</em> importiert."
notify_member_create_reservation:
your_reservation_RESERVABLE_was_successfully_saved_html: "Ihre Reservierung <strong><em>%{RESERVABLE}</em></strong> wurde erfolgreich gespeichert."
notify_member_reservation_reminder:
reminder_you_have_a_reservation_RESERVABLE_to_be_held_on_DATE_html: "Erinnerung: Sie haben eine Reservierung <strong>%{RESERVABLE}</strong> für <em>%{DATE}</em>"
notify_member_slot_is_canceled:
your_reservation_RESERVABLE_of_DATE_was_successfully_cancelled: "Ihre Reservierung %{RESERVABLE} von %{DATE} wurde erfolgreich storniert."
notify_member_slot_is_modified:
your_reservation_slot_was_successfully_changed: "Ihr Reservierungsslot wurde erfolgreich geändert."
notify_member_subscribed_plan:
you_have_subscribed_to_PLAN_html: "Sie haben <strong><em>%{PLAN}</em></strong> abonniert."
notify_member_subscribed_plan_is_changed:
you_have_changed_your_subscription_to_PLAN_html: "Sie haben Ihr Abonnement für <strong><em>%{PLAN}</em></strong> geändert."
notify_member_subscription_canceled:
your_subscription_PLAN_was_successfully_cancelled_html: "Ihr Abonnement von <strong><em>%{PLAN}</em></strong> wurde erfolgreich storniert."
notify_member_subscription_extended:
your_subscription_PLAN_has_been_extended_FREE_until_DATE_html: "Ihr Abonnement von <strong><em>{PLAN}</em></strong> wurde {FREE, select, true{kostenlos} other{}} bis {DATE} verlängert." #messageFormat interpolation
notify_member_subscription_is_expired:
your_subscription_has_expired: "Ihr Abonnement ist abgelaufen."
notify_member_subscription_will_expire_in_7_days:
your_subscription_will_expire_in_7_days: "Ihr Abonnement läuft in 7 Tagen ab."
notify_partner_subscribed_plan:
subscription_partner_PLAN_has_been_subscribed_by_USER_html: "Das Partnerabonnement <strong><em>%{PLAN}</em></strong> wurde von <strong><em>%{USER}</strong></em> abonniert."
notify_project_author_when_collaborator_valid:
USER_became_collaborator_of_your_project: "%{USER} nimmt nun teil an Ihrem Projekt:"
notify_project_collaborator_to_valid:
you_are_invited_to_collaborate_on_the_project: "Sie wurden zur Teilnahme am Projekt eingeladen:"
notify_user_auth_migration:
your_account_was_migrated: "Ihr Konto wurde erfolgreich in das neue Authentifizierungssystem migriert."
notify_user_profile_complete:
your_profile_was_completed: "Ihr Profil ist vollständig, Sie haben nun Zugriff auf die gesamte Plattform."
notify_user_training_valid:
your_TRAINING_was_validated_html: "Ihre Schulung <strong><em>%{TRAINING}</em></strong> wurde erfolgreich überprüft."
notify_user_user_group_changed:
your_group_has_changed: "Ihre Gruppe hat sich geändert."
notify_user_when_avoir_ready:
your_avoir_is_ready_html: "Ihre Rückerstattungsrechnung #%{REFERENCE}, über %{AMOUNT} wurde erstellt. <a href='api/invoices/%{INVOICE_ID}/download' target='_blank'>Hier herunterladen</a>."
notify_user_when_invoice_ready:
your_invoice_is_ready_html: "Ihre Rechnung #%{REFERENCE}, über %{AMOUNT} wurde erstellt. <a href='api/invoices/%{INVOICE_ID}/download' target='_blank'>Hier herunterladen</a>."
undefined_notification:
unknown_notification: "Unbekannte Benachrichtigung"
notification_ID_wrong_type_TYPE_unknown: "Benachrichtigung %{ID} falsch (Typ %{TYPE} unbekannt)"
notify_user_wallet_is_credited:
your_wallet_is_credited: "Eine Gutschrift wurde ihrem Konto gutgeschrieben von einem Administrator"
notify_admin_user_wallet_is_credited:
wallet_is_credited: "Dem Guthaben des Mitglieds %{USER} wurde %{AMOUNT} gutgeschrieben"
notify_admin_export_complete:
export: "Der Export"
statistics_global: "aller Statistiken"
statistics_account: "der Registrierungsstatistiken"
statistics_event: "der Veranstaltungsstatistiken"
statistics_machine: "der Statistiken der Maschinenslots"
statistics_project: "der Projektstatistiken"
statistics_subscription: "der Abonnementstatistiken"
statistics_training: "der Schulungsstatistiken"
statistics_space: "der Raumstatistiken"
users_members: "der Mitgliederliste"
users_subscriptions: "der Abonnementliste"
users_reservations: "der Reservierungsliste"
availabilities_index: "der Verfügbarkeit der Reservierungen"
accounting_acd: "der Rechnungsdaten für ACD"
is_over: "ist beendet."
download_here: "Hier herunterladen"
notify_admin_import_complete:
import_over: "%{CATEGORY} Import ist beendet. "
members: "Mitglieder"
view_results: "Ergebnisse anzeigen."
notify_member_about_coupon:
enjoy_a_discount_of_PERCENT_with_code_CODE: "Erhalten Sie %{PERCENT}% Rabatt mit dem Code %{CODE}"
enjoy_a_discount_of_AMOUNT_with_code_CODE: "Erhalten Sie %{AMOUNT}% Rabatt mit dem Code %{CODE}"
notify_admin_free_disk_space:
warning_free_disk_space: "Warnung: Auf dem Server ist noch %{AVAILABLE} MiB Speicherplatz verfügbar"
notify_admin_close_period_reminder:
warning_last_closed_period_over_1_year: "Bitte schließen Sie Ihre Abrechnungsperioden regelmäßig ab. Der letzte Abschlusszeitraum endete um %{LAST_END}"
warning_no_closed_periods: "Bitte schließen Sie Ihre Abrechnungsperioden regelmäßig ab. Sie müssen Abrechnungsperioden ab %{FIRST_DATE} schließen"
notify_admin_archive_complete:
archive_complete: "Die Datenarchivierung von %{START} bis %{END} ist abgeschlossen. <a href='api/accounting_periods/%{ID}/archive' target='_blank'>Datenarchiv herunterladen</a>. Speichern Sie das Archiv auf einem externen, gesicherten Datenträger."
notify_privacy_policy_changed:
policy_updated: "Änderung der Datenschutz-Bestimmungen"
click_to_show: "Zum Anzeigen hier klicken"
notify_admin_refund_created:
refund_created: "Eine Rückerstattung von %{AMOUNT} wurde für Benutzer %{USER} erstellt"
notify_user_role_update:
your_role_is_ROLE: "Ihre Rolle wurde in %{ROLE} geändert."
notify_admins_role_update:
user_NAME_changed_ROLE_html: "Benutzer <strong><em>%{NAME}</strong></em> ist jetzt %{ROLE}."
notify_admin_members_stripe_sync:
all_members_sync: "Alle Mitglieder wurden erfolgreich auf Stripe synchronisiert."
#statistics tools for admins
statistics:
subscriptions: "Abonnements"
machines_hours: "Maschinen-Slots"
spaces: "Räume"
trainings: "Schulungen"
events: "Veranstaltungen"
registrations: "Anmeldungen"
projects: "Projekte"
users: "Benutzer"
training_id: "Schulungs-ID"
training_date: "Schulungstermin"
event_id: "Veranstaltungs-ID"
event_date: "Veranstaltungsdatum"
event_name: "Veranstaltungsname"
event_theme: "Thema"
age_range: "Altersklasse"
themes: "Themen"
components: "Komponenten"
machines: "Maschinen"
user_id: "Nutzer-ID"
bookings: "Buchungen"
hours_number: "Stundenzahl"
tickets_number: "Ticket Nummer"
revenue: "Einnahmen"
account_creation: "Benutzerkontenerstellung"
project_publication: "Projektveröffentlichung"
duration: "Dauer"
#statistics exports to the excel file format
export:
entries: "Einträge"
revenue: "Einnahmen"
average_age: "Durchschnittsalter"
total: "Gesamt"
date: "Datum"
user: "Nutzer"
email: "E-Mail"
phone: "Telefon"
gender: "Geschlecht"
age: "Alter"
type: "Typ"
male: "Männlich"
female: "Weiblich"
#initial price's category for events, created to replace the old "reduced amount" property
price_category:
reduced_fare: "Ermäßigter Tarif"
reduced_fare_if_you_are_under_25_student_or_unemployed: "Ermäßigter Tarif, wenn Sie unter 25, studierend oder arbeitslos sind."
group:
#name of the user's group for administrators
admins: 'Administratoren'

View File

@ -0,0 +1,63 @@
#Additional translations at https://github.com/plataformatec/devise/wiki/I18n
de:
devise:
confirmations:
confirmed: "Ihr Account wurde erfolgreich bestätigt."
send_instructions: "Sie erhalten in Kürze eine E-Mail mit Anweisungen zur Bestätigung Ihres Accounts."
send_paranoid_instructions: "Wenn Ihre E-Mail-Adresse in unserer Datenbank existiert, werden Sie in Kürze eine E-Mail mit Anweisungen erhalten, wie Sie Ihr Konto bestätigen."
failure:
already_authenticated: "Sie sind bereits angemeldet."
inactive: "Ihr Konto wurde noch nicht aktiviert."
invalid: "Ungültige E-Mail-Adresse oder Passwort."
locked: "Ihr Account ist gesperrt."
last_attempt: "Sie haben noch einen weiteren Versuch, bevor Ihr Konto gesperrt wird."
not_found_in_database: "Ungültige E-Mail-Adresse oder Passwort."
timeout: "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an."
unauthenticated: "Sie müssen sich anmelden oder registrieren, bevor Sie fortfahren."
unconfirmed: "Sie müssen Ihr Konto bestätigen, bevor Sie fortfahren. Bitte klicken Sie auf den Link unter dem Formular."
mailer:
confirmation_instructions:
action: "Meine E-Mail-Adresse bestätigen"
instruction: "Sie können Ihre Registrierung abschließen, indem Sie Ihre E-Mail-Adresse bestätigen. Bitte klicken Sie auf den folgenden Link:"
subject: "Anleitung zur Bestätigung Ihres Accounts"
reset_password_instructions:
action: "Mein Passwort ändern"
instruction: "Ein Link zur Änderung ihres Passwortes wurde angefordert. Sie können Ihr Passwort über diesen Link ändern."
ignore_otherwise: "Falls Sie kein neues Passwort angefordert haben, ignorieren Sie bitte diese Nachricht."
subject: "Anleitung für das Zurücksetzen Ihres Passworts"
unlock_instructions:
subject: "Anweisungen zum Entsperren"
omniauth_callbacks:
failure: "Sie konnten auf %{kind} nicht authentifiziert werden. Grund: \"%{reason}\"."
success: "Erfolgreich über den Account %{kind} authentifiziert."
passwords:
no_token: "Diese Seite kann nur über eine E-Mail zur Passwort-Zurücksetzung aufgerufen werden. Wenn Sie über eine solche E-Mail auf die Seite zugreifen, vergewissern Sie sich, dass die URL vollständig und korrekt ist."
send_instructions: "Sie erhalten in Kürze eine Email mit Anweisungen, wie Sie Ihr Passwort zurücksetzen können."
send_paranoid_instructions: "Wenn Ihre E-Mail-Adresse in unserer Datenbank vorhanden ist, erhalten Sie in Kürze eine E-Mail mit einem Link zur Passwortwiederherstellung."
updated: "Ihr Passwort wurde erfolgreich geändert. Sie sind jetzt angemeldet."
updated_not_active: "Ihr Passwort wurde erfolgreich geändert."
registrations:
destroyed: "Auf Wiedersehen! Ihr Account wurde erfolgreich gelöscht. Wir hoffen, Sie bald wiederzusehen."
signed_up: "Willommen! Ihre Registierung war erfolgreich."
signed_up_but_inactive: "Sie haben sich erfolgreich registiert. Sie können sich jedoch erst nach der Aktivierung Ihres Accounts anmelden."
signed_up_but_locked: "Sie haben sich erfolgreich registriert. Wir konnten Sie jedoch nicht anmelden, weil Ihr Account gesperrt ist."
signed_up_but_unconfirmed: "Eine Nachricht mit einem Bestätigungslink wurde an Ihre E-Mail-Adresse gesendet. Öffnen Sie bitte den Link, um Ihr Konto zu aktivieren."
update_needs_confirmation: "Sie haben Ihr Konto erfolgreich aktualisiert. Wir müssen allerdings Ihre neue E-Mail-Adresse verifizieren. Bitte überprüfen Sie Ihr Postfach und klicken Sie auf den Bestätigungslink, um die Bestätigung Ihrer neuen E-Mail-Adresse abzuschließen."
updated: "Sie haben Ihren Account erfolgreich aktualisiert."
sessions:
signed_in: "Anmeldung erfolgreich."
signed_out: "Sie sind nun abgemeldet."
unlocks:
send_instructions: "Sie werden in Kürze eine E-Mail mit Anweisungen erhalten, wie Sie Ihr Konto entsperren."
send_paranoid_instructions: "Falls Ihr Konto existiert, erhalten Sie in wenigen Minuten eine E-Mail mit Anweisungen, wie Sie es entsperren können."
unlocked: "Ihr Account wurde erfolgreich entsperrt. Bitte melden Sie sich an, um fortzufahren."
errors:
messages:
already_confirmed: "Diese E-Mail wurde bereits bestätigt. Bitte melden Sie sich an."
confirmation_period_expired: "muss innerhalb von %{period} bestätigt werden. Bitte neu anfordern"
expired: "ist abgelaufen, bitte neu anfordern"
not_found: "Die E-Mail wurde nicht gefunden"
not_locked: "war nicht gesperrt"
not_saved:
one: "Ein Fehler hat verhindert, dass %{resource} gespeichert werden konnte:"
other: "%{count} Fehler haben verhindert, dass %{resource} gespeichert werden konnte:"

View File

@ -39,6 +39,7 @@ en:
must_be_in_the_past: "The period must be strictly prior to today's date."
apipie:
api_documentation: "API Documentation"
code: "HTTP code"
#error messages when importing an account from a SSO
omniauth:
email_already_linked_to_another_account_please_input_your_authentication_code: "E-mail address \"%{OLD_MAIL}\" is already linked to another account, please input your authentication code."
@ -112,6 +113,18 @@ en:
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Subscription of %{NAME} extended (Free days) starting from %{STARTDATE} until %{ENDDATE}"
and: 'and'
invoice_text_example: "Our association is not subject to VAT"
#PDF payment schedule generation
payment_schedules:
schedule_reference: "Payment schedule reference: %{REF}"
schedule_issued_on_DATE: "Schedule issued on %{DATE}"
object: "Object: Payment schedule for %{ITEM}"
subscription_of_NAME_for_DURATION_starting_from_DATE: "the subscription of %{NAME} for %{DURATION} starting from %{DATE}"
deadlines: "Table of your deadlines"
deadline_date: "Payment date"
deadline_amount: "Amount including tax"
total_amount: "Total amount"
settlement_by_METHOD: "Debits will be made by {METHOD, select, stripe{card} other{check}} for each deadlines."
settlement_by_wallet: "%{AMOUNT} will be debited from your wallet to settle the first deadline."
# CVS accounting export (columns headers)
accounting_export:
journal_code: "Journal code"
@ -344,6 +357,14 @@ en:
user_NAME_changed_ROLE_html: "User <strong><em>%{NAME}</strong></em> is now %{ROLE}."
notify_admin_members_stripe_sync:
all_members_sync: "All members were successfully synchronized on Stripe."
notify_user_when_payment_schedule_ready:
your_schedule_is_ready_html: "Your payment schedule #%{REFERENCE}, of %{AMOUNT}, is ready. <a href='api/payment_schedules/%{SCHEDULE_ID}/download' target='_blank'>Click here to download</a>."
notify_admin_payment_schedule_failed:
schedule_failed: "Failed card debit for the %{DATE} deadline, for schedule %{REFERENCE}"
notify_member_payment_schedule_failed:
schedule_failed: "Failed card debit for the %{DATE} deadline, for your schedule %{REFERENCE}"
notify_admin_payment_schedule_check_deadline:
schedule_deadline: "You must cash the check for the %{DATE} deadline, for schedule %{REFERENCE}"
#statistics tools for admins
statistics:
subscriptions: "Subscriptions"

View File

@ -39,6 +39,7 @@ es:
must_be_in_the_past: "El período debe ser estrictamente anterior a la fecha de hoy."
apipie:
api_documentation: "Documentación API"
code: "HTTP code"
#error messages when importing an account from a SSO
omniauth:
email_already_linked_to_another_account_please_input_your_authentication_code: "El correo electrónico \"%{OLD_MAIL}\" ya está ligado a otra cuenta, ingrese su código de autenticación."

View File

@ -39,6 +39,7 @@ fr:
must_be_in_the_past: "La période doit être strictement antérieure à la date du jour."
apipie:
api_documentation: "Documentation de l'API"
code: "Code HTTP "
#error messages when importing an account from a SSO
omniauth:
email_already_linked_to_another_account_please_input_your_authentication_code: "L'adresse de courriel \"%{OLD_MAIL}\" est déjà associée à un compte utilisateur, merci de saisir votre code d'authentification."
@ -112,6 +113,18 @@ fr:
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Prolongement Abonnement (Jours gratuits) de %{NAME} à compter du %{STARTDATE} jusqu'au %{ENDDATE}"
and: 'et'
invoice_text_example: "Notre association n'est pas assujettie à la TVA"
#PDF payment schedule generation
payment_schedules:
schedule_reference: "Référence de l'échéancier : %{REF}"
schedule_issued_on_DATE: "Échéancier édité le %{DATE}"
object: "Objet : Échéancier de paiement de %{ITEM}"
subscription_of_NAME_for_DURATION_starting_from_DATE: "l'abonnement de %{NAME} pour %{DURATION} à compter du %{DATE}"
deadlines: "Tableau de vos mensualités"
deadline_date: "Date du prélèvement"
deadline_amount: "Montant TTC"
total_amount: "Montant total"
settlement_by_METHOD: "Les prélèvements seront effectués par {METHOD, select, stripe{carte bancaire} other{chèque}} à l'échéance."
settlement_by_wallet: "%{AMOUNT} seront prélevés de votre porte-monnaie pour régler la première échéance."
#CVS accounting export (columns headers)
accounting_export:
journal_code: "Code journal"
@ -344,6 +357,14 @@ fr:
user_NAME_changed_ROLE_html: "L'utilisateur <strong><em>%{NAME}</strong></em> est maintenant %{ROLE}."
notify_admin_members_stripe_sync:
all_members_sync: "Tous les membres ont été synchronisés avec succès sur Stripe."
notify_user_when_payment_schedule_ready:
your_schedule_is_ready_html: "Votre échéancier n°%{REFERENCE}, d'un montant de %{AMOUNT}, est prêt. <a href='api/payment_schedules/%{SCHEDULE_ID}/download' target='_blank'>Cliquez ici pour le télécharger</a>."
notify_admin_payment_schedule_failed:
schedule_failed: "Échec du prélèvement par carte de l'échéance du %{DATE}, pour l'échéancier %{REFERENCE}"
notify_member_payment_schedule_failed:
schedule_failed: "Échec du prélèvement par carte de l'échéance du %{DATE}, pour votre échéancier %{REFERENCE}"
notify_admin_payment_schedule_check_deadline:
schedule_deadline: "Vous devez encaisser le chèque de l'échéance du %{DATE}, pour l'échéancier %{REFERENCE}"
#statistics tools for admins
statistics:
subscriptions: "Abonnements"

291
config/locales/mails.de.yml Normal file
View File

@ -0,0 +1,291 @@
de:
layouts:
notifications_mailer:
see_you_later: "Bis bald auf {GENDER, select, neutral{} other{das}}" #messageFormat interpolation
sincerely: "Mit freundlichen Grüßen,"
signature: "Das Fab Lab Team."
do_not_reply: "Bitte antworte nicht auf diese E-Mail."
users_mailer:
notify_user_account_created:
subject: "Dein FabLab Account wurde erfolgreich erstellt"
body:
hello: "Hallo %{NAME},"
intro: "Das FabLab-Team hat Ihren Account eingerichtet auf der {FABLAB}-Website:" #messageFormat interpolation
connection_parameters: "Hier sind Ihre Verbindungsparameter:"
account_name: "Kontoname:"
password: "Passwort:"
temporary_password: "Dies ist ein temporäres Passwort. Sie können es in Ihrem «Mein Konto»-Bereich ändern."
keep_advantages: "Mit diesem Konto behalten Sie alle Vorteile (Schulungen, Abonnementpläne), die mit Ihrem FabLab-Benutzerprofil verbunden sind."
to_use_platform: "Um die Website zu nutzen, bitte"
logon_or_login: "erstellen Sie ein neues Konto oder melden Sie sich an, indem Sie hier klicken."
token_if_link_problem: "Wenn Sie Probleme mit dem Link haben, können Sie den folgenden Code bei Ihrem ersten Verbindungsversuch eingeben:"
notifications_mailer:
notify_user_user_group_changed:
subject: "Ihre Gruppe wurde geändert"
body:
warning: "Sie haben die Gruppe gewechselt. Im FabLab kann geprüft werden, ob diese Änderung zulässig ist."
notify_admin_user_group_changed:
subject: "Ein Mitglied hat die Gruppe geändert"
body:
user_changed_group_html: "Benutzer <em><strong>%{NAME}</strong></em> hat die Gruppe geändert."
previous_group: "Vorherige Gruppe:"
new_group: "Neue Gruppe:"
notify_admin_subscription_extended:
subject: "Ein Abonnement wurde verlängert"
body:
subscription_extended_html: "Das Abonnement <strong><em>{PLAN}</em></strong> des Nutzers <strong><em>{NAME}</strong></em> wurde {FREE, select, true{kostenlos} other{}} verlängert bis {DATE}." #messageFormat interpolation
notify_member_subscription_extended:
subject: "Ihr Abonnement wurde verlängert"
body:
your_plan: "Ihr Abonnement"
has_been_extended: "wurde verlängert"
free: "kostenlos"
until: "bis"
notify_partner_subscribed_plan:
subject: "Ein Abonnement wurde gekauft"
body:
a_plan: "Ein Abonnement"
was_purchased_by_member: "wurde vom Nutzer gekauft"
notify_admin_when_project_published:
subject: "Ein Projekt wurde veröffentlicht"
body:
new_project_published: "Ein neues Projekt wurde veröffentlicht:"
notify_project_collaborator_to_valid:
subject: "Einladung zur Zusammenarbeit an einem Projekt"
body:
your_are_invited_to_take_part_in_a_project: "Sie wurden eingeladen, an einem Projekt mitzuarbeiten:"
to_accept_the_invitation_click_on_following_link: "Um diese Einladung anzunehmen, klicken Sie bitte auf den folgenden Link:"
notify_project_author_when_collaborator_valid:
subject: "Neuer Mitarbeiter in Ihrem Projekt"
body:
the_member: "der Benutzer"
accepted_your_invitation_to_take_part_in_the_project: "hat Ihre Einladung zur Projektmitarbeit angenommen:"
notify_user_training_valid:
subject: "Ihre Schulung wurde validiert"
body:
your_training: "Ihre Schulung"
has_been_validated: "wurde validiert"
notify_member_subscribed_plan:
subject: "Ihr Abonnement wurde erfolgreich gekauft"
body:
plan_subscribed_html: "Sie haben <strong><em>%{PLAN}</em></strong> abonniert."
rolling_subscription_stops_on: "Dein Abonnement endet %{DURATION} nach Ihrer ersten Schulung. Andernfalls wird es am %{DATE} angehalten."
subscription_stops_on: "Ihr Abonnement endet am %{DATE}."
notify_member_create_reservation:
subject: "Ihre Reservierung wurde erfolgreich gespeichert"
body:
reservation_saved_html: "Ihre Reservierung <strong><em>%{RESERVATION}</em></strong> wurde erfolgreich gespeichert"
your_reserved_slots: "Ihre reservierten Slots sind:"
notify_member_subscribed_plan_is_changed:
subject: "Ihr Abonnement wurde aktualisiert"
body:
new_plan_html: "Sie haben Ihr Abonnement für <strong><em>%{PLAN}</em></strong> geändert."
notify_admin_member_create_reservation:
subject: "Neue Reservierung"
body:
member_reserved_html: "Nutzer %{NAME} hat <strong><em>%{RESERVABLE}</em></strong> reserviert."
reserved_slots: "Reservierte Slots sind:"
notify_member_slot_is_modified:
subject: "Ihr Reservierungsslot wurde erfolgreich geändert"
body:
reservation_changed_to: "Ihr Reservierungs-Slot wurde geändert zu:"
previous_date: "Vorheriges Datum:"
notify_admin_slot_is_modified:
subject: "Ein reservierter Slot wurde geändert"
body:
slot_modified: "Benutzer %{NAME} hatte seinen Reservierungs-Slot geändert"
new_date: "Neuer Slot"
old_date: "Vorheriger Slot"
notify_admin_when_user_is_created:
subject: "Ein Benutzerkonto wurde erstellt"
body:
new_account_created: "Ein neues Benutzerkonto wurde auf der Website erstellt:"
account_for_organization: "Dieses Konto verwaltet eine Organisation:"
notify_admin_subscribed_plan:
subject: "Ein Abonnement wurde gekauft"
body:
plan_subscribed_html: "Das Abonnement <strong><em>%{PLAN}</em></strong> wurde von <strong><em>%{NAME}</strong></em> abgeschlossen."
notify_member_invoice_ready:
subject: "Rechnung Ihres FabLabs"
body:
please_find_attached_html: "Die angehängte Datei enthält Ihre Rechnung von {DATE}, über den Betrag von {AMOUNT} in Bezug auf Ihr/e {TYPE, select, Reservation{Reservierung} other{Abonnement}}." #messageFormat interpolation
invoice_in_your_dashboard_html: "Sie können auf Ihre Rechnung in %{DASHBOARD} auf der FabLab-Website zugreifen."
your_dashboard: "Ihr Dashboard"
notify_member_reservation_reminder:
subject: "Reservierungserinnerung"
body:
this_is_a_reminder_about_your_reservation_RESERVABLE_to_be_held_on_DATE_html: "Erinnerung: Sie haben eine Reservierung <strong>%{RESERVABLE}</strong> für <em>%{DATE}</em>"
this_reservation_concerns_the_following_slots: "Diese Reservierung betrifft folgende Slots:"
notify_member_avoir_ready:
subject: "Die Rückerstattungsrechnung Ihres FabLabs"
body:
please_find_attached_html: "Die angehängte Datei enthält Ihre Rückerstattungsrechnung von {DATE}, über den Betrag von {AMOUNT} in Bezug auf Ihr/e {TYPE, select, Reservation{Reservierung} other{Abonnement}}." #messageFormat interpolation
invoice_in_your_dashboard_html: "Sie können auf Ihre Rückerstattungsrechnung in %{DASHBOARD} auf der FabLab-Website zugreifen."
your_dashboard: "Ihr Dashboard"
notify_member_subscription_will_expire_in_7_days:
subject: "Ihr Abonnement läuft in 7 Tagen ab"
body:
your_plan: "Ihr Plan"
expires_in_7_days: "läuft in 7 Tagen ab."
to_renew_your_plan_follow_the_link: "Bitte folgen Sie diesem Link, um Ihren Plan zu erneuern"
notify_member_subscription_is_expired:
subject: "Ihr Abonnement ist abgelaufen"
body:
your_plan: "Ihr Plan"
has_expired: "ist abgelaufen."
you_can_go_to: "Bitte gehen Sie zu"
to_renew_your_plan: "um Ihren Plan zu erneuern"
notify_admin_subscription_will_expire_in_7_days:
subject: "Ein Mitgliedsabonnement läuft in 7 Tagen ab"
body:
subscription_will_expire_html: "Abonnement für Benutzer %{NAME} <strong><em>%{PLAN}</em></strong> läuft in 7 Tagen ab."
notify_admin_subscription_is_expired:
subject: "Ein Mitgliedsabonnement ist abgelaufen"
body:
subscription_expired_html: "Abonnementplan für Benutzer %{NAME} <strong><em>%{PLAN}</em></strong> ist jetzt abgelaufen."
notify_admin_subscription_canceled:
subject: "Ein Mitgliedsabonnement wurde storniert"
body:
subscription_canceled_html: "Abonnement <strong><em>%{PLAN}</em></strong> für Nutzer %{NAME} wurde storniert."
notify_member_subscription_canceled:
subject: "Ihr Abonnement wurde storniert"
body:
your_plan_was_canceled: "Ihr Abonnementsplan wurde storniert."
your_plan: "ihr Abonnement"
end_at: "endet am"
notify_member_slot_is_canceled:
subject: "Ihre Reservierung wurde storniert"
body:
reservation_canceled: "Ihre Reservierung für %{RESERVABLE} wurde storniert"
notify_admin_slot_is_canceled:
subject: "Eine Reservierung wurde storniert"
body:
member_cancelled: "Benutzer %{NAME} hat seine Reservierung storniert"
item_details: "%{START} - %{END}, in Bezug auf %{RESERVABLE}"
generate_refund: "Vergessen Sie nicht, eine Gutschrift oder eine Rückerstattung für diese Stornierung zu buchen."
notify_admin_when_user_is_imported:
subject: "Ein Benutzerkonto wurde aus der SSO importiert"
body:
new_account_imported: "Ein neues Benutzerkonto (ID: %{ID}) wurde über %{PROVIDER} auf die Website importiert."
provider_uid: "seine Provider-ID ist: "
known_information: "Folgendes wissen wir über diesen Anbieter:"
address_already_used: "Diese Adresse wird schon von einem anderen Nutzer verwendet"
no_more_info_available: "Für diesen Nutzer sind keine weiteren Informationen verfügbar, solange er sein Profil nicht vervollständigt hat."
notify_user_profile_complete:
subject: "Sie haben nun Zugriff auf die gesamte Website"
body:
message: "Ihre Kontoinformationen wurden korrekt aktualisiert, Sie haben nun Zugriff auf die gesamte Website."
notify_user_auth_migration:
subject: "Wichtige Änderung Ihres FabLab Accounts"
body:
the_platform: "die Website"
is_changing_its_auth_system_and_will_now_use: "ändert momentan das Benutzeridentifikationssystem und verwendet zukünftig"
instead_of: "anstatt"
consequence_of_the_modification: "Aufgrund dieser Änderung können Sie sich nicht mit Ihren momentanen Benutzernamen auf der Website anmelden"
to_use_the_platform_thanks_for: "Um die Webseite weiter zu nutzen, bitte"
create_an_account_on: "erstellen Sie ein Konto auf"
or_use_an_existing_account_clicking_here: "oder verwenden Sie ein bestehendes Konto, indem Sie hier klicken"
in_case_of_problem_enter_the_following_code: "Falls beim Aufruf des Links zu Problemen kommt, können Sie den folgenden Code bei Ihrem ersten Verbindungsversuch eingeben, um Ihr aktuelles Konto in das neue Authentifizierungssystem zu migrieren:"
notify_admin_user_merged:
subject: "Ein importiertes Konto wurde mit einem bestehenden Konto zusammengeführt"
body:
imported_account_merged: "Ein zuvor importiertes Benutzerkonto über %{PROVIDER) wurde mit dem bestehenden Konto %{NAME} zusammengeführt"
provider_uid: "seine Provider-ID ist:"
notify_admin_profile_complete:
subject: "Ein importiertes Konto hat sein Profil vervollständigt"
body:
account_completed: "Ein Benutzerkonto hat sein Profil vervollständigt:"
imported_account_completed: "Ein Benutzerkonto, das zuvor über %{PROVIDER} importiert wurde, hat sein Profil vervollständigt:"
provider_id: "seine Provider-ID ist:"
notify_admin_abuse_reported:
subject: "Ein missbräuchlicher Inhalt wurde gemeldet"
body:
intro: "Ein Benutzer wurde als beleidigend markiert"
signaled_content: "gemeldeter Inhalt:"
signaled_by: "gemeldet von:"
signaled_on: "gemeldet auf:"
message: "Nachricht:"
visit_management_interface: "Weitere Informationen finden Sie im Bereich Reporting Management."
notify_user_wallet_is_credited:
subject: "Eine Gutschrift ist auf Ihrem Konto eingegangen"
body:
wallet_credit_html: "Ihrem Guthaben wurde %{AMOUNT} vom Administrator gutgeschrieben."
notify_admin_user_wallet_is_credited:
subject: "Dem Guthaben des Mitglieds wurde gutgeschrieben"
body:
wallet_credit_html: "Dem Guthaben von %{USER} wurde %{AMOUNT} vom Administrator %{ADMIN} gutgeschrieben."
notify_admin_export_complete:
subject: "Export abgeschlossen"
body:
you_asked_for_an_export: "Sie haben einen Export angefordert"
statistics_global: "aller Statistiken"
statistics_account: "der Registrierungsstatistiken"
statistics_event: "der Veranstaltungsstatistiken"
statistics_machine: "der Statistiken der Maschinenslots"
statistics_project: "der Projektstatistiken"
statistics_subscription: "der Abonnementstatistiken"
statistics_training: "der Schulungsstatistiken"
statistics_space: "der Raumstatistiken"
users_members: "der Mitgliederliste"
users_subscriptions: "der Abonnementliste"
users_reservations: "der Reservierungsliste"
availabilities_index: "der Verfügbarkeit der Reservierungen"
accounting_accounting-software: "der Buchhaltungsdaten"
click_to_download: "Excel-Datei erfolgreich erstellt. Zum Herunterladen klicken Sie"
here: "hier"
file_type:
xlsx: "Excel"
csv: "CSV"
notify_admin_import_complete:
subject: "Import abgeschlossen"
body:
you_made_an_import: "Sie haben einen Import von %{CATEGORY} gestartet"
category_members: "der Mitglieder"
click_to_view_results: "Klicken Sie hier, um die Ergebnisse anzuzeigen"
notify_member_about_coupon:
subject: "Gutschein"
body:
enjoy_a_discount_of_PERCENT_with_code_CODE: "Erhalten Sie %{PERCENT}% Rabatt auf der gesamten Seite mit dem Code %{CODE}."
enjoy_a_discount_of_AMOUNT_with_code_CODE: "Erhalten Sie %{AMOUNT}% Rabatt auf der gesamten Seite mit dem Code %{CODE}."
this_coupon_is_valid_USAGE_times_until_DATE_for_all_your_purchases: "Dieser Gutschein ist {USAGE, plural, =1{einmalig} other{mehrfach}} gültig für alle Ihre Käufe {TYPE, select, amount_off{mindestens gleich dem Gutscheinbetrag} other{}} ab sofort {DATE, select, NO-DATE{und ohne Ablaufdatum} other{und einlösbar bis {DATE}}}."
notify_admin_free_disk_space:
subject: "Wenig Speicherplatz auf der Festplatte"
body: "Warnung: verfügbarer Festplattenspeicher auf dem Server mit Fab-Manager ist weniger als %{THRESHOLD} MiB. Dies kann den Betrieb beeinflussen und das Speichern von Daten verhindern. Derzeit sind %{AVAILABLE} MiB freier Speicherplatz am Mount-Punkt verfügbar."
notify_admin_close_period_reminder:
subject: "Bitte schließen Sie Ihre Abrechnungsperioden regelmäßig ab"
body:
warning_last_closed_period_over_1_year: "Bitte schließen Sie Ihre Abrechnungsperioden regelmäßig ab. Der letzte Abschlusszeitraum endete um %{LAST_END}."
warning_no_closed_periods: "Bitte schließen Sie Ihre Abrechnungsperioden regelmäßig ab. Sie müssen Abrechnungsperioden ab %{FIRST_DATE} schließen."
notify_admin_archive_complete:
subject: "Archivierung abgeschlossen"
body:
archive_complete: "Sie haben den Abrechnungszeitraum von %{START} bis %{END} abgeschlossen. Die Archivierung der Daten ist nun abgeschlossen."
click_to_download: "Um das ZIP-Archiv herunterzuladen, klicken Sie"
here: "hier."
save_on_secured: "Speichern Sie dieses Archiv auf einem gesicherten externen Speichermedium und bedenken Sie, dass es bei einer Überprüfung durch die Steuerbehörde angefordert werden kann."
notify_privacy_policy_changed:
subject: "Datenschutzerklärung aktualisiert"
body:
content_html: "<p>Wir möchten Sie darüber informieren, dass wir unsere Datenschutzrichtlinie gerade aktualisiert haben.</p><p>Wir können unsere Datenschutzrichtlinien jederzeit ändern. Gesetzesgemäß erhalten Sie eine Benachrichtigung für jedes Update.</p><p>Durch den Zugriff auf oder die Nutzung unserer Dienste nach dem Update der Datenschutzrichtlinien gehen wir davon aus, dass Sie den Bedingungen einschließlich der Aktualisierungen zugestimmt haben.</p>"
link_to_policy: "Klicken Sie hier, um sich die Datenschutzerklärung anzusehen."
notify_admin_refund_created:
subject: "Eine Rückerstattung wurde durchgeführt"
body:
refund_created: "Eine Rückerstattung von %{AMOUNT} wurde auf die Rechnung %{INVOICE} des Benutzers %{USER} generiert"
download: "Hier klicken, um diese Erstattungsrechnung herunterzuladen"
notify_admins_role_update:
subject: "Die Rolle eines Benutzers hat sich geändert"
body:
user_role_changed_html: "Die Rolle des Benutzers <em><strong>%{NAME}</strong></em> hat sich geändert."
previous_role: "Vorherige Rolle:"
new_role: "Neue Rolle:"
notify_user_role_update:
subject: "Ihre Rolle hat sich geändert"
body:
role_changed_html: "Deine Rolle bei {GENDER, select, male{dem} female{der} neutral{} other{dem}} {NAME} hat sich geändert. Sie sind jetzt <strong>{ROLE}</strong>.<br/>Mit großer Macht kommt große Verantwortung, nutzen Sie Ihre neuen Privilegien fair und respektvoll."
notify_admin_members_stripe_sync:
subject: "Stripe-Synchronisation"
body:
members_sync: "Alle Mitglieder wurden erfolgreich auf Stripe synchronisiert."
shared:
hello: "Hallo %{user_name}"

View File

@ -287,5 +287,29 @@ en:
subject: "Stripe synchronization"
body:
members_sync: "All members were successfully synchronized on Stripe."
notify_member_payment_schedule_ready:
subject: "Your payment schedule"
body:
please_find_attached_html: "Please find attached your payment schedule, issued on {DATE}, with an amount of {AMOUNT} concerning your {TYPE, select, Reservation{reservation} other{subscription}}." #messageFormat interpolation
schedule_in_your_dashboard_html: "You can find this payment schedule at any time from %{DASHBOARD} on the Fab Lab's website."
your_dashboard: "your dashboard"
notify_admin_payment_schedule_failed:
subject: "Card debit failure"
body:
remember: "In accordance with the %{REFERENCE} payment schedule, a debit by card of %{AMOUNT} was scheduled on %{DATE}."
error: "Unfortunately, this card debit was unable to complete successfully."
action: "Please go to your payment schedule management interface as soon as possible to resolve the problem."
notify_member_payment_schedule_failed:
subject: "Card debit failure"
body:
remember: "In accordance with your %{REFERENCE} payment schedule, a debit by card of %{AMOUNT} was scheduled on %{DATE}."
error: "Unfortunately, this card debit was unable to complete successfully."
action: "Please contact the manager of your FabLab as soon as possible, otherwise your subscription may be interrupted."
notify_admin_payment_schedule_check_deadline:
subject: "Payment deadline"
body:
remember: "In accordance with the %{REFERENCE} payment schedule, %{AMOUNT} was due to be debited on %{DATE}."
date: "This is a reminder to cash the scheduled check as soon as possible."
confirm: "Do not forget to confirm the receipt in your payment schedule management interface, so that the corresponding invoice will be generated."
shared:
hello: "Hello %{user_name}"

View File

@ -287,5 +287,29 @@ fr:
subject: "Synchronisation Stripe"
body:
members_sync: "Tous les membres ont été synchronisés avec succès sur Stripe."
notify_member_payment_schedule_ready:
subject: "Votre échéancier de paiement"
body:
please_find_attached_html: "Vous trouverez en pièce jointe votre échéancier de paiement du {DATE}, d'un montant de {AMOUNT} concernant votre {TYPE, select, Reservation{réservation} other{abonnement}}." #messageFormat interpolation
schedule_in_your_dashboard_html: "Vous pouvez à tout moment retrouver votre échéancier dans %{DASHBOARD} sur le site du Fab Lab."
your_dashboard: "votre tableau de bord"
notify_admin_payment_schedule_failed:
subject: "Échec du prélèvement par carte"
body:
remember: "Conformément à l'échéancier de paiement %{REFERENCE}, un prélèvement par carte de %{AMOUNT} était prévu le %{DATE}."
error: "Malheureusement, ce prélèvement n'a pas pu être effectué correctement."
action: "Veuillez vous rendre au plus tôt dans votre interface de gestion des échéanciers pour régler le problème."
notify_member_payment_schedule_failed:
subject: "Échec du prélèvement par carte"
body:
remember: "Conformément à votre échéancier de paiement %{REFERENCE}, un prélèvement par carte de %{AMOUNT} était prévu le %{DATE}."
error: "Malheureusement, ce prélèvement n'a pas pu être effectué correctement."
action: "Veuillez prendre contact avec le gestionnaire de votre FabLab au plus tôt, faute de quoi votre abonnement risque d'être interrompu."
notify_admin_payment_schedule_check_deadline:
subject: "Échéance d'encaissement"
body:
remember: "Conformément à l'échéancier de paiement %{REFERENCE}, une échéance de %{AMOUNT} était prévu pour être prélevée le %{DATE}."
date: "Ceci est un rappel d'encaisser le chèque prévu dès que possible."
confirm: "N'oubliez pas de confirmer l'encaissement dans votre interface de gestion des échéanciers, afin que la facture correspondante soit générée."
shared:
hello: "Bonjour %{user_name}"

View File

@ -39,6 +39,7 @@ pt:
must_be_in_the_past: "O período deve ser estritamente anterior à data de hoje."
apipie:
api_documentation: "Documentação da API"
code: "HTTP code"
#error messages when importing an account from a SSO
omniauth:
email_already_linked_to_another_account_please_input_your_authentication_code: "E-mail \"%{OLD_MAIL}\" já está vinculado a outra conta, insira seu código de autenticação."

View File

@ -1,198 +0,0 @@
af:
date:
abbr_day_names:
- Son
- Maan
- Dins
- Woe
- Don
- Vry
- Sat
abbr_month_names:
-
- Jan
- Feb
- Mar
- Apr
- Mei
- Jun
- Jul
- Aug
- Sep
- Okt
- Nov
- Des
day_names:
- Sondag
- Maandag
- Dinsdag
- Woensdag
- Donderdag
- Vrydag
- Saterdag
formats:
default: "%Y-%m-%d"
long: "%B %d, %Y"
short: "%b %d"
month_names:
-
- Januarie
- Februarie
- Maart
- April
- Mai
- Junie
- Julie
- Augustus
- September
- Oktober
- November
- Desember
order:
- :year
- :month
- :day
datetime:
distance_in_words:
about_x_hours:
one: ongeveer 1 uur
other: ongeveer %{count} ure
about_x_months:
one: ongeveer 1 maand
other: ongeveer %{count} maande
about_x_years:
one: ongeveer 1 jaar
other: ongeveer %{count} jaar
almost_x_years:
one: sowat 1 jaar
other: sowat %{count} jaar
half_a_minute: halfminuut
less_than_x_minutes:
one: minder as n minuut
other: minder as %{count} minute
less_than_x_seconds:
one: minder as 1 second
other: minder as %{count} sekondes
over_x_years:
one: meer as 1 jaar
other: meer as %{count} jaar
x_days:
one: 1 dag
other: "%{count} days"
x_minutes:
one: 1 minuut
other: "%{count} minute"
x_months:
one: 1 maand
other: "%{count} maande"
x_seconds:
one: 1 sekonde
other: "%{count} sekondes"
prompts:
day: Dag
hour: Uur
minute: Minuut
month: Maand
second: Sekondes
year: Jaar
errors:
format: "%{attribute} %{message}"
messages:
accepted: moet aanvaar word
blank: mag nie leeg wees nie
confirmation: pas nie by bevestiging nie
empty: mag nie leeg wees nie
equal_to: moet gelyk wees aan %{count}
even: moet gelykstaande wees
exclusion: is bespreek
greater_than: moet meer wees as %{count}
greater_than_or_equal_to: moet meer of gelykstaande wees aan %{count}
inclusion: is nie by die lys ingesluit nie
invalid: is ongeldig
less_than: moet minder wees as %{count}
less_than_or_equal_to: moet minder of gelykstaande wees aan %{count}
not_a_number: is nie n getal nie
not_an_integer: moet n integer wees
odd: moet onewe wees
record_invalid: 'Validation failed: %{errors}'
taken: is reeds geneem
too_long:
one: is te lank (maksimum is 1 karakter)
other: is te lank (maksimum is %{count} karakters)
too_short:
one: is te kort (minimum is 1 karakter)
other: is te kort (minimum is %{count} karakters)
wrong_length:
one: is die verkeerde lengte (moet 1 karakter wees)
other: is die verkeerde lengte (moet %{count} karakters wees)
template:
body: 'There were problems with the following fields:'
header:
one: 1 fout het verhoed dat hierdie %{model} gestoor kon word
other: "%{count} foute het verhoed dat hierdie %{model} gestoor kon word"
helpers:
select:
prompt: Kies asseblief
submit:
create: Skep %{model}
submit: Stoor %{model}
update: Dateer %{model} op
number:
currency:
format:
delimiter: ","
format: "%u%n"
precision: 2
separator: "."
significant: vals
strip_insignificant_zeros: vals
unit: R
format:
delimiter: ","
precision: 3
separator: "."
significant: vals
strip_insignificant_zeros: vals
human:
decimal_units:
format: "%n %u"
units:
billion: miljard
million: miljoen
quadrillion: kwadriljon
thousand: duisend
trillion: biljoen
unit: ''
format:
delimiter: ''
precision: 3
significant: waar
strip_insignificant_zeros: waar
storage_units:
format: "%n %u"
units:
byte:
one: Byte
other: Bytes
gb: GB
kb: KB
mb: MB
tb: TB
percentage:
format:
delimiter: ''
precision:
format:
delimiter: ''
support:
array:
last_word_connector: ", en "
two_words_connector: " en "
words_connector: ", "
time:
am: vm
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
long: "%B %d, %Y %H:%M"
short: "%d %b %H:%M"
pm: nm

View File

@ -1,274 +0,0 @@
ar:
date:
abbr_day_names:
- الأحد
- الإثنين
- الثّلاثاء
- الأربعاء
- الخميس
- الجمعة
- السّبت
abbr_month_names:
-
- يناير/كانون الثّاني
- فبراير/شباط
- مارس/آذَار
- إبريل/نَيْسان
- مايو/أيار
- يونيو/حَزيران
- يوليو/تمُّوز
- أغسطس/آب
- سبتمبر/أيلول
- أكتوبر/تشرين الأوّل
- نوفمبر/تشرين الثّاني
- ديسمبر/كانون الأَوّل
day_names:
- الأحد
- الإثنين
- الثّلاثاء
- الأربعاء
- الخميس
- الجمعة
- السّبت
formats:
default: "%Y-%m-%d"
long: "%B %e، %Y"
short: "%e %b"
month_names:
-
- يناير/كانون الثّاني
- فبراير/شباط
- مارس/آذَار
- إبريل/نَيْسان
- مايو/أيار
- يونيو/حَزيران
- يوليو/تمُّوز
- أغسطس/آب
- سبتمبر/أيلول
- أكتوبر/تشرين الأوّل
- نوفمبر/تشرين الثّاني
- ديسمبر/كانون الأَوّل
order:
- :day
- :month
- :year
datetime:
distance_in_words:
about_x_hours:
zero: حوالي صفر ساعات
one: حوالي ساعة واحدة
two: حوالي ساعتان
few: حوالي %{count} ساعات
many: حوالي %{count} ساعة
other: حوالي %{count} ساعة
about_x_months:
zero: حوالي صفر أشهر
one: حوالي شهر واحد
two: حوالي شهران
few: حوالي %{count} أشهر
many: حوالي %{count} شهر
other: حوالي %{count} شهر
about_x_years:
zero: حوالي صفر سنوات
one: حوالي سنة
two: حوالي سنتان
few: حوالي %{count} سنوات
many: حوالي %{count} سنة
other: حوالي %{count} سنة
almost_x_years:
zero: ما يقرب من صفر سنوات
one: تقريبا سنة واحدة
two: ما يقرب من سنتين
few: ما يقرب من %{count} سنوات
many: ما يقرب من %{count} سنة
other: ما يقرب من %{count} سنة
half_a_minute: نصف دقيقة
less_than_x_minutes:
zero: أقل من صفر دقائق
one: أقل من دقيقة
two: أقل من دقيقتان
few: أقل من %{count} دقائق
many: أقل من %{count} دقيقة
other: أقل من %{count} دقيقة
less_than_x_seconds:
zero: أقل من صفر ثواني
one: أقل من ثانية
two: أقل من ثانيتان
few: أقل من %{count} ثوان
many: أقل من %{count} ثانية
other: أقل من %{count} ثانية
over_x_years:
zero: أكثر من صفر سنوات
one: أكثر من سنة
two: أكثر من سنتين
few: أكثر من %{count} سنوات
many: أكثر من %{count} سنة
other: أكثر من %{count} سنة
x_days:
zero: صفر أيام
one: يوم واحد
two: يومان
few: "%{count} أيام"
many: "%{count} يوم"
other: "%{count} يوم"
x_minutes:
zero: صفر دقائق
one: دقيقة واحدة
two: دقيقتان
few: "%{count} دقائق"
many: "%{count} دقيقة"
other: "%{count} دقيقة"
x_months:
zero: صفر أشهر
one: شهر واحد
two: شهران
few: "%{count} أشهر"
many: "%{count} شهر"
other: "%{count} شهر"
x_seconds:
zero: صفر ثواني
one: ثانية واحدة
two: ثانيتان
few: "%{count} ثوان"
many: "%{count} ثانية"
other: "%{count} ثانية"
prompts:
day: اليوم
hour: ساعة
minute: دقيقة
month: الشهر
second: ثانية
year: السنة
errors:
format: "%{attribute} %{message}"
messages:
accepted: يجب أن تقبل
blank: فارغ، يرجى ملء الحقل
present: يجب ترك الحقل فارغاً
confirmation: لا يتوافق مع %{attribute}
empty: فارغ، يرجى ملء الحقل
equal_to: يجب أن يساوي %{count}
even: يجب أن يكون عددًا زوجيًّا
exclusion: محجوز
greater_than: يجب أن يكون أكبر من %{count}
greater_than_or_equal_to: يجب أن يكون أكبر من أو يساوي %{count}
inclusion: غير مُدرج في القائمة
invalid: غير مقبول
less_than: يجب أن يكون أصغر من %{count}
less_than_or_equal_to: يجب أن يكون أصغر من أو يساوي %{count}
not_a_number: ليس رقمًا
not_an_integer: يجب أن يكون عدداً صحيحاً
odd: يجب أن يكون عددًا فرديًّا
record_invalid: 'فشل التحقّق من: %{errors}'
restrict_dependent_destroy:
one: لا يمكن حذف السجل لوجود سجل يعتمد عليه %{record}
many: لا يمكن حذف السجل لوجود سجلات تعتمد عليه %{record}
taken: محجوز مُسبقًا
too_long:
zero: أطول من اللّازم (الحد الأقصى هو ولا حرف)
one: أطول من اللّازم (الحد الأقصى هو حرف واحد)
two: أطول من اللّازم (الحد الأقصى هو حرفان)
few: أطول من اللّازم (الحد الأقصى هو %{count} حروف)
many: أطول من اللّازم (الحد الأقصى هو %{count} حرف)
other: أطول من اللّازم (الحد الأقصى هو %{count} حرف)
too_short:
zero: أقصر من اللّازم (الحد الأدنى هو ولا حرف)
one: أقصر من اللّازم (الحد الأدنى هو حرف واحد)
two: أقصر من اللّازم (الحد الأدنى هو حرفان)
few: أقصر من اللّازم (الحد الأدنى هو %{count} حروف)
many: أقصر من اللّازم (الحد الأدنى هو %{count} حرف)
other: أقصر من اللّازم (الحد الأدنى هو %{count} حرف)
wrong_length:
zero: الطول غير مطابق للحد المطلوب (يجب أن يكون ولا حرف)
one: الطول غير مطابق للحد المطلوب (يجب أن يكون حرف واحد)
two: الطول غير مطابق للحد المطلوب (يجب أن يكون حرفان)
few: الطول غير مطابق للحد المطلوب (يجب أن يكون %{count} أحرف)
many: الطول غير مطابق للحد المطلوب (يجب أن يكون %{count} حرف)
other: الطول غير مطابق للحد المطلوب (يجب أن يكون %{count} حرف)
other_than:
zero: الطول يجب ألاّ يكون صفر أحرف
one: الطول يجب ألاّ يكون حرفاً وحداً
two: الطول يجب ألاّ يكون حرفان
few: الطول يجب ألاّ يكون %{count} أحرف
many: الطول يجب ألاّ يكون %{count} حرفاً
other: الطول يجب ألاّ يكون %{count} حرفاً
template:
body: 'يُرجى التحقّق من الحقول التّالية:'
header:
zero: 'ليس بالامكان حفظ %{model}: لايوجد أخطاء.'
one: 'ليس بالامكان حفظ %{model}: خطأ واحد.'
two: 'ليس بالامكان حفظ %{model}: خطئان.'
few: 'ليس بالامكان حفظ %{model}: %{count} أخطاء.'
many: 'ليس بالامكان حفظ %{model}: %{count} أخطاء.'
other: 'ليس بالامكان حفظ %{model}: %{count} خطأ.'
helpers:
select:
prompt: يُرجى الاختيار
submit:
create: "%{model} إنشاء"
submit: "%{model} حِفظ"
update: "%{model} تحديث"
number:
currency:
format:
delimiter: "،"
format: "%u%n"
precision: 2
separator: "."
significant: false
strip_insignificant_zeros: false
unit: "$"
format:
delimiter: "،"
precision: 3
separator: "."
significant: false
strip_insignificant_zeros: false
human:
decimal_units:
format: "%n %u"
units:
billion: مليار
million: مليون
quadrillion: كدريليون
thousand: ألفّ
trillion: تريليون
unit: ''
format:
delimiter: ''
precision: 3
significant: true
strip_insignificant_zeros: true
storage_units:
format: "%n %u"
units:
byte:
zero: Bytes
one: Byte
two: Bytes
few: Bytes
many: Bytes
other: Bytes
gb: GB
kb: KB
mb: MB
tb: TB
percentage:
format:
delimiter: ''
format: "%n%"
precision:
format:
delimiter: ''
support:
array:
last_word_connector: " و "
two_words_connector: " و "
words_connector: " و "
time:
am: صباحًا
formats:
default: "%a %b %d %H:%M:%S %Z %Y"
long: "%B %d, %Y %H:%M"
short: "%d %b %H:%M"
pm: مساءً

View File

@ -1,192 +0,0 @@
az:
date:
abbr_day_names:
- B.
- B.E.
- Ç.A.
- Ç.
- C.A.
- C.
- Ş.
abbr_month_names:
-
- Yan
- Fev
- Mar
- Apr
- May
- İyn
- İyl
- Avq
- Sen
- Okt
- Noy
- Dek
day_names:
- Bazar
- Bazar ertəsi
- Çərşənbə axşamı
- Çərşənbə
- Cümə axşamı
- Cümə
- Şənbə
formats:
default: "%d.%m.%Y"
long: "%d %B %Y"
short: "%d %b"
month_names:
-
- Yanvar
- Fevral
- Mart
- Aprel
- May
- İyun
- İyul
- Avqust
- Sentyabr
- Oktyabr
- Noyabr
- Dekabr
order:
- :day
- :month
- :year
datetime:
distance_in_words:
about_x_hours:
one: təxminən 1 saat
other: təxminən %{count} saat
about_x_months:
one: təxminən 1 ay
other: təxminən %{count} ay
about_x_years:
one: təxminən 1 il
other: təxminən %{count} il
almost_x_years:
one: təqribən 1 il
other: təqribən %{count} il
half_a_minute: yarım dəqiqə
less_than_x_minutes:
one: 1 dəqiqədən az
other: "%{count} dəqiqədən az"
less_than_x_seconds:
one: 1 saniyədən az
other: "%{count} saniyədən az"
over_x_years:
one: 1 ildən çox
other: "%{count} ildən çox"
x_days:
one: 1 gün
other: "%{count} gün"
x_minutes:
one: 1 dəqiqə
other: "%{count} dəqiqə"
x_months:
one: 1 ay
other: "%{count} ay"
x_seconds:
one: 1 saniyə
other: "%{count} saniyə"
prompts:
day: Gün
hour: Saat
minute: Dəqiqə
month: Ay
second: Saniyə
year: İl
errors:
format: "%{attribute} %{message}"
messages:
accepted: qəbul olunmalıdır
blank: boş ola bilməz
confirmation: təsdiqə uygun deyil
empty: boş ola bilməz
equal_to: "%{count}-ə bərabər olmalıdır"
even: cüt olmalıdır
exclusion: qorunur
greater_than: "%{count}-dən böyük olmalıdır"
greater_than_or_equal_to: böyük və ya %{count}-ə bərabər olmalıdır
inclusion: siyahiyə daxil deyil
invalid: yalnışdır
less_than: "%{count}-dən kiçik olmalıdır"
less_than_or_equal_to: kiçik və ya %{count}-ə bərabər olmalıdır
not_a_number: rəqəm deyil
not_an_integer: tam rəqəm olmalıdır
odd: tək olmalıdır
record_invalid: 'Yoxlama uğursuz oldu: %{errors}'
taken: artıq mövcuddur
too_long: çox uzundur (%{count} simvoldan çox olmalı deyil)
too_short: çox qısadır (%{count} simvoldan az olmalı deyil)
wrong_length: uzunluqu səhvdir (%{count} simvol olmalıdır)
template:
body: 'Aşağıdaki səhvlər üzə çıxdı:'
header:
one: "%{model} saxlanmadı: 1 səhv"
other: "%{model} saxlanmadı: %{count} səhv"
helpers:
select:
prompt: Seçin
submit:
create: "%{model} yarat"
submit: "%{model} saxla"
update: "%{model} yenilə"
number:
currency:
format:
delimiter: " "
format: "%n %u"
precision: 2
separator: "."
significant: false
strip_insignificant_zeros: false
unit: AZN
format:
delimiter: " "
precision: 3
separator: "."
significant: false
strip_insignificant_zeros: false
human:
decimal_units:
format: "%n %u"
units:
billion: Milyard
million: Milyon
quadrillion: Katrilyon
thousand: Min
trillion: Trilyon
unit: ''
format:
delimiter: ''
precision: 1
significant: false
strip_insignificant_zeros: false
storage_units:
format: "%n %u"
units:
byte:
one: Bayt
other: Bayt
gb: GB
kb: KB
mb: MB
tb: TB
percentage:
format:
delimiter: ''
precision:
format:
delimiter: ''
support:
array:
last_word_connector: " və "
two_words_connector: " və "
words_connector: ", "
time:
am: günortaya qədər
formats:
default: "%a, %d %b %Y, %H:%M:%S %z"
long: "%d %B %Y, %H:%M"
short: "%d %b, %H:%M"
pm: günortadan sonra

View File

@ -1,204 +0,0 @@
be:
date:
abbr_day_names:
- Пан
- Аўт
- Сер
- Чцв
- Пят
- Суб
- Ндз
abbr_month_names:
-
- Сту
- Лют
- Сак
- Кра
- Тра
- Чэр
- Ліп
- Жні
- Вер
- Кас
- Ліс
- Сне
day_names:
- Нядзеля
- Панядзелак
- Аўторак
- Серада
- Чацвер
- Пятніца
- Субота
formats:
default: "%d-%m-%Y"
long: "%B %d, %Y"
short: "%b %d"
month_names:
-
- Студзень
- Люты
- Сакавік
- Красавік
- Травень
- Чэрвень
- Ліпень
- Жнівень
- Верасень
- Кастрычнік
- Лістапад
- Снежань
order:
- :day
- :month
- :year
datetime:
distance_in_words:
about_x_hours:
one: каля 1 гадзіны
other: каля %{count} гадзін
about_x_months:
one: каля 1 месяца
other: каля %{count} месяцаў
about_x_years:
one: каля 1 года
other: каля %{count} гадоў
almost_x_years:
one: амаль 1 год
other: амаль %{count} гадоў
half_a_minute: палова хвіліны
less_than_x_minutes:
one: меней за 1 хвіліну
other: меней за %{count} хвілін
less_than_x_seconds:
one: меней за 1 секунду
other: меней за %{count} секундаў
over_x_years:
one: болей за 1 год
other: болей за %{count} гадоў
x_days:
one: 1 дзень
other: "%{count} дзён"
x_minutes:
one: 1 хвіліна
other: "%{count} хвілін"
x_months:
one: 1 месяц
other: "%{count} месяцаў"
x_seconds:
one: 1 секунда
other: "%{count} секундаў"
prompts:
day: Дзень
hour: Гадзіна
minute: Хвіліна
month: Месяц
second: Секунда
year: Год
errors:
format: "%{attribute} %{message}"
messages:
accepted: трэба прыняць
blank: не можа быць пустым
present: павінна быць пустым
confirmation: не супадае з %{attribute}
empty: не можа быць пустым
equal_to: павінна быць роўным %{count}
even: павінна быць цотным
exclusion: мае зарэзерваванае значэнне
greater_than: павінна быць болей за %{count}
greater_than_or_equal_to: павінна быць болей ці роўным %{count}
inclusion: значэнне не уключана ў спіс
invalid: няправільнае значэнне
less_than: павінна быць меней за %{count}
less_than_or_equal_to: павінна быць меней ці роўным %{count}
not_a_number: гэта не лічба
not_an_integer: павінна быць цэлай лічбай
odd: павінна быць няцотным
record_invalid: 'Памылкі валідацыі: %{errors}'
restrict_dependent_destroy:
one: Нельга выдаліць запіс, таму што існуе залежнасць %{record}
many: Нельга выдаліць запіс, таму што існуюць залежнасці %{record}
taken: ўжо занята
too_long:
one: занадта доўгі (максімум 1 сімвал)
other: занадта доўгі (максімум %{count} сімвалаў)
too_short:
one: занадта кароткі (мінімум 1 сімвал)
other: занадта кароткі (мінімум %{count} сімвалаў)
wrong_length:
one: няправільная даўжыня (павінен быць 1 сімвал)
other: няправільная даўжыня (павінны быць %{count} сімвалаў)
other_than: павінна адрознівацца ад %{count}
template:
body: 'Узніклі праблемы з наступнымі палямі:'
header:
one: не атрымалася захаваць %{model} з-за 1 памылкі
other: не атрымалася захаваць %{model} з-за %{count} памылак
helpers:
select:
prompt: Калі ласка, абярыце
submit:
create: Стварыць %{model}
submit: Захаваць %{model}
update: Абнавіць %{model}
number:
currency:
format:
delimiter: ","
format: "%u%n"
precision: 2
separator: "."
significant: false
strip_insignificant_zeros: false
unit: "$"
format:
delimiter: ","
precision: 3
separator: "."
significant: false
strip_insignificant_zeros: false
human:
decimal_units:
format: "%n %u"
units:
billion: мільярд
million: мільён
quadrillion: квадрыльён
thousand: тысяча
trillion: трыльён
unit: ''
format:
delimiter: ''
precision: 3
significant: true
strip_insignificant_zeros: true
storage_units:
format: "%n %u"
units:
byte:
one: Байт
other: Байтаў
gb: ГБ
kb: КБ
mb: МБ
tb: ТБ
percentage:
format:
delimiter: ''
format: "%n%"
precision:
format:
delimiter: ''
support:
array:
last_word_connector: " і "
two_words_connector: " і "
words_connector: ", "
time:
am: раніцы
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
long: "%B %d, %Y %H:%M"
short: "%d %b %H:%M"
pm: вечара

Some files were not shown because too many files have changed in this diff Show More