feat: enhance translation and invoice layout
This commit is contained in:
@ -1,47 +1,46 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
import * as plugins from "./plugins.js";
|
||||
import * as interfaces from "./interfaces/index.js";
|
||||
|
||||
const fromContact: plugins.tsclass.business.IContact = {
|
||||
name: 'Awesome From Company',
|
||||
type: 'company',
|
||||
description: 'a company that does stuff',
|
||||
name: "Awesome From Company",
|
||||
type: "company",
|
||||
description: "a company that does stuff",
|
||||
address: {
|
||||
streetName: 'Awesome Street',
|
||||
houseNumber: '5',
|
||||
city: 'Bremen',
|
||||
country: 'Germany',
|
||||
postalCode: '28359',
|
||||
streetName: "Awesome Street",
|
||||
houseNumber: "5",
|
||||
city: "Bremen",
|
||||
country: "Germany",
|
||||
postalCode: "28359",
|
||||
},
|
||||
vatId: 'DE12345678',
|
||||
vatId: "DE12345678",
|
||||
sepaConnection: {
|
||||
bic: 'BPOTBEB1',
|
||||
iban: 'BE01234567891616'
|
||||
bic: "BPOTBEB1",
|
||||
iban: "BE01234567891616",
|
||||
},
|
||||
email: 'hello@awesome.company',
|
||||
phone: '+49 421 1234567',
|
||||
fax: '+49 421 1234568',
|
||||
|
||||
email: "hello@awesome.company",
|
||||
phone: "+49 421 1234567",
|
||||
fax: "+49 421 1234568",
|
||||
};
|
||||
|
||||
const toContact: plugins.tsclass.business.IContact = {
|
||||
name: 'Awesome To GmbH',
|
||||
type: 'company',
|
||||
customerNumber: 'LL-CLIENT-123',
|
||||
description: 'a company that does stuff',
|
||||
name: "Awesome To GmbH",
|
||||
type: "company",
|
||||
customerNumber: "LL-CLIENT-123",
|
||||
description: "a company that does stuff",
|
||||
address: {
|
||||
streetName: 'Awesome Street',
|
||||
houseNumber: '5',
|
||||
city: 'Bremen',
|
||||
country: 'Germany',
|
||||
postalCode: '28359'
|
||||
streetName: "Awesome Street",
|
||||
houseNumber: "5",
|
||||
city: "Bremen",
|
||||
country: "Germany",
|
||||
postalCode: "28359",
|
||||
},
|
||||
vatId: 'BE12345678',
|
||||
}
|
||||
vatId: "BE12345678",
|
||||
};
|
||||
|
||||
export const demoLetter: plugins.tsclass.business.ILetter = {
|
||||
versionInfo: {
|
||||
type: 'draft',
|
||||
version: '1.0.0',
|
||||
type: "draft",
|
||||
version: "1.0.0",
|
||||
},
|
||||
accentColor: null,
|
||||
content: {
|
||||
@ -49,155 +48,192 @@ export const demoLetter: plugins.tsclass.business.ILetter = {
|
||||
timesheetData: null,
|
||||
contractData: {
|
||||
contractDate: Date.now(),
|
||||
id: 'someid'
|
||||
id: "someid",
|
||||
},
|
||||
letterData: {} as plugins.tsclass.business.ILetter,
|
||||
invoiceData: {
|
||||
id: 'LL-INV-48765',
|
||||
id: "LL-INV-48765",
|
||||
reverseCharge: true,
|
||||
dueInDays: 30,
|
||||
billedBy: fromContact,
|
||||
billedTo: toContact,
|
||||
status: null,
|
||||
deliveryDate: new Date().getTime(),
|
||||
periodOfPerformance: null,
|
||||
periodOfPerformance: {
|
||||
from: +new Date().setDate(new Date().getDate() - 7),
|
||||
to: +new Date(),
|
||||
},
|
||||
printResult: null,
|
||||
currency: 'EUR',
|
||||
currency: "EUR",
|
||||
notes: [],
|
||||
type: 'debitnote',
|
||||
type: "debitnote",
|
||||
items: [
|
||||
{
|
||||
name: 'Item with 19% VAT',
|
||||
name: "Item with 19% VAT",
|
||||
unitQuantity: 2,
|
||||
unitNetPrice: 100,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
name: 'Item with 7% VAT',
|
||||
name: "Item with 7% VAT",
|
||||
unitQuantity: 4,
|
||||
unitNetPrice: 100,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 7,
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
name: 'Item with 7% VAT',
|
||||
name: "Item with 7% VAT",
|
||||
unitQuantity: 3,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 7,
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
name: 'Item with 21% VAT',
|
||||
name: "Item with 21% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 21,
|
||||
position: 3,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 6,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 4,
|
||||
},{
|
||||
name: 'Item with 19% VAT',
|
||||
},
|
||||
{
|
||||
name: "Item with 19% VAT",
|
||||
unitQuantity: 8,
|
||||
unitNetPrice: 100,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 5,
|
||||
},
|
||||
{
|
||||
name: 'Item with 7% VAT',
|
||||
name: "Item with 7% VAT",
|
||||
unitQuantity: 9,
|
||||
unitNetPrice: 100,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 7,
|
||||
position: 6,
|
||||
},
|
||||
{
|
||||
name: 'Item with 7% VAT',
|
||||
name: "Item with 7% VAT",
|
||||
unitQuantity: 4,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 7,
|
||||
position: 8,
|
||||
},
|
||||
{
|
||||
name: 'Item with 21% VAT',
|
||||
name: "Item with 21% VAT",
|
||||
unitQuantity: 3,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 21,
|
||||
position: 9,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 10,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 10,
|
||||
position: 11,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 10,
|
||||
position: 12,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 10,
|
||||
position: 13,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 10,
|
||||
position: 14,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 10,
|
||||
position: 15,
|
||||
},
|
||||
{
|
||||
name: 'Item with 0% VAT',
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: 'hours',
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 10,
|
||||
position: 16,
|
||||
},
|
||||
{
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 17,
|
||||
},
|
||||
{
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 18,
|
||||
},
|
||||
{
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 19,
|
||||
},
|
||||
{
|
||||
name: "Item with 0% VAT",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 230,
|
||||
unitType: "hours",
|
||||
vatPercentage: 0,
|
||||
position: 20,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
date: Date.now(),
|
||||
type: 'invoice',
|
||||
type: "invoice",
|
||||
needsCoverSheet: false,
|
||||
objectActions: [],
|
||||
pdf: null,
|
||||
@ -208,12 +244,12 @@ export const demoLetter: plugins.tsclass.business.ILetter = {
|
||||
legalContact: null,
|
||||
logoUrl: null,
|
||||
pdfAttachments: null,
|
||||
subject: 'Invoice: LL-INV-48765',
|
||||
}
|
||||
subject: "Invoice: LL-INV-48765",
|
||||
};
|
||||
|
||||
export const demoDocumentSettings: interfaces.IDocumentSettings = {
|
||||
enableTopDraftText: true,
|
||||
enableDefaultHeader: true,
|
||||
enableDefaultFooter: true,
|
||||
languageCode: 'DE',
|
||||
};
|
||||
languageCode: "DE",
|
||||
};
|
||||
|
@ -1,12 +1,15 @@
|
||||
export const a4Height = 1122;
|
||||
export const a4Width = 794;
|
||||
export const rightMargin = 70;
|
||||
export const leftMargin = 90;
|
||||
const DPI = 96 / 2.54; // <PX> / <INCH>
|
||||
export const A4_HEIGHT = cmToPx(29.7); // DPI * 29.7cm
|
||||
export const A4_WIDTH = cmToPx(21); // DPI * 21cm
|
||||
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
export function cmToPx(value: number): number {
|
||||
return DPI * value;
|
||||
}
|
||||
|
||||
import * as interfaces from "./interfaces/index.js";
|
||||
export { interfaces };
|
||||
|
||||
import * as translation from './translation.js';
|
||||
import * as translation from "./translation.js";
|
||||
export { translation };
|
||||
|
||||
export * from './demoletter.js';
|
||||
export * from "./demoletter.js";
|
||||
|
@ -1,9 +1,23 @@
|
||||
import * as translation from '../translation.js';
|
||||
import * as translation from "../translation.js";
|
||||
|
||||
export interface IDocumentTheme {
|
||||
colorPrimaryForeground?: string;
|
||||
colorPrimaryBackground?: string;
|
||||
colorAccentForeground?: string;
|
||||
colorAccentBackground?: string;
|
||||
fontFamily?: string;
|
||||
pageBackground?: string;
|
||||
coverPageBackground?: string;
|
||||
}
|
||||
|
||||
export interface IDocumentSettings {
|
||||
enableTopDraftText?: boolean;
|
||||
enableDefaultHeader?: boolean;
|
||||
enableDefaultFooter?: boolean;
|
||||
languageCode?: translation.TLanguageCode;
|
||||
enableFoldMarks?: boolean;
|
||||
enableInvoiceContractRefSection?: boolean;
|
||||
languageCode?: translation.LanguageCode;
|
||||
dateStyle?: Intl.DateTimeFormatOptions["dateStyle"];
|
||||
vatGroupPositions?: boolean;
|
||||
}
|
||||
theme?: IDocumentTheme;
|
||||
}
|
||||
|
@ -1,143 +1,272 @@
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
// Define English translations without enforcing TTranslationImplementation yet
|
||||
export const EN_translations = {
|
||||
address: 'Address',
|
||||
bankConnection: 'Bank Connection',
|
||||
contactInfo: 'Contact Info',
|
||||
description: 'Description',
|
||||
invoice: 'Invoice',
|
||||
itemPos: 'Item Pos.',
|
||||
quantity: 'Quantity',
|
||||
registrationInfo: 'Registration Info',
|
||||
reverseVatNote: 'VAT arises on a reverse charge basis and is payable by the customer.',
|
||||
totalNetPrice: 'Total Net Price',
|
||||
unitNetPrice: 'Unit Net Price',
|
||||
unitType: 'Unit Type',
|
||||
yourCustomerId: 'Your Customer ID:',
|
||||
yourVatId: 'Your vat id on file:',
|
||||
continuesOnPage: 'Continues on page',
|
||||
finalPageStatement: 'This is the final page of this document.',
|
||||
page: 'Page',
|
||||
vatShort: 'VAT',
|
||||
} as const;
|
||||
address: "Address",
|
||||
"bank.accountHolder": "beneficiary",
|
||||
"bank.bic": "bic",
|
||||
"bank.iban": "iban",
|
||||
"bank.institution": "institution",
|
||||
"bankConnection@@title": "Bank Connection",
|
||||
"contact@@title": "Contact Info",
|
||||
"customer.number": "Your Customer ID",
|
||||
description: "Description",
|
||||
"empty.logo": "no logo provided",
|
||||
"empty.number.customer": "not registered",
|
||||
empty: "not provided",
|
||||
fax: "Fax",
|
||||
introStatement: "We hereby invoice the following products and services",
|
||||
"invoice.number": "Invoice number",
|
||||
invoice: "Invoice",
|
||||
"item.position": "Pos.",
|
||||
mail: "Mail",
|
||||
"overlay@@draft": "Draft",
|
||||
"page.continueNext": "Continues on page",
|
||||
"page.final": "This is the final page of this document.",
|
||||
page: "Page",
|
||||
pageOf: "of",
|
||||
"payment.qr": "Pay via QR code",
|
||||
"payment.qr.description": "Scan the QR code with you banking app",
|
||||
"payment.terms": "Payment Terms",
|
||||
"payment.terms.direct": "Without deduction until",
|
||||
"periodOfPerformance.day": "Delivery Date",
|
||||
"periodOfPerformance.range": "Delivery Period",
|
||||
phone: "Phone",
|
||||
"price.total.net": "Total Net Price",
|
||||
"price.unit.net": "Unit Net Price",
|
||||
price: "Price",
|
||||
quantity: "Quantity",
|
||||
referencedContract: "Referenced contract",
|
||||
"referencedContract.text":
|
||||
"This invoice is adhering to agreements made by contract between the parties on",
|
||||
"registration.label": "Registration Info",
|
||||
subject: "Subject",
|
||||
sum: "Sum",
|
||||
totalGross: "Total gross",
|
||||
"unit.type": "Unit Type",
|
||||
"vat.position": "on item positions",
|
||||
"vat.reverseCharge.note":
|
||||
"VAT arises on a reverse charge basis and is payable by the customer.",
|
||||
"vat.short": "VAT",
|
||||
"vat.yourId": "Your vat id on file",
|
||||
vat: "Valued Added Tax",
|
||||
};
|
||||
|
||||
// Infer keys of EN_translations
|
||||
export type TTranslationKey = keyof typeof EN_translations;
|
||||
|
||||
/**
|
||||
* For example:
|
||||
* - price
|
||||
*/
|
||||
type RawTranslationKeys = keyof typeof EN_translations;
|
||||
|
||||
/**
|
||||
* For example:
|
||||
* - price.item
|
||||
* - price.sum
|
||||
* - price.unit
|
||||
* - vat.yourId
|
||||
*/
|
||||
type NestedTranslationKeys =
|
||||
| RawTranslationKeys
|
||||
| `${RawTranslationKeys}.${string}`
|
||||
| `${RawTranslationKeys}.${string}.${string}`
|
||||
| `${RawTranslationKeys}.${string}.${string}.${string}`
|
||||
| `${RawTranslationKeys}.${string}.${string}.${string}.${string}`;
|
||||
|
||||
/**
|
||||
* For example:
|
||||
* - contact@@mail
|
||||
* - vat = 'VAT'
|
||||
* - vat.yourId = 'your vat id'
|
||||
* - footer@@vat.yourId = 'your vat id'
|
||||
* - header@@vat.yourId = 'THIS IS YOUR VAT'
|
||||
*/
|
||||
type LocationBasedTranslationKeys = `${string}@@${NestedTranslationKeys}`;
|
||||
|
||||
/**
|
||||
* Mix of everything
|
||||
*/
|
||||
export type TranslationKey =
|
||||
| NestedTranslationKeys
|
||||
| LocationBasedTranslationKeys;
|
||||
|
||||
// Define the type for all translations based on EN_translations keys
|
||||
export type TTranslationImplementation = {
|
||||
[key in TTranslationKey]: string;
|
||||
export type Dictionary = {
|
||||
[key in TranslationKey]: string;
|
||||
};
|
||||
|
||||
// Define German translations
|
||||
export const DE_translations: TTranslationImplementation = {
|
||||
address: 'Adresse',
|
||||
bankConnection: 'Bankverbindung',
|
||||
contactInfo: 'Kontaktinformationen',
|
||||
description: 'Beschreibung',
|
||||
invoice: 'Rechnung',
|
||||
itemPos: 'Pos.',
|
||||
quantity: 'Anzahl',
|
||||
registrationInfo: 'HRA/HRB Info',
|
||||
reverseVatNote:
|
||||
'Umkehr der Umsatzsteuerpflicht: Der Rechnungsempfänger ist für die korrekte Abrechnung der Umsatzsteuer zuständig.',
|
||||
totalNetPrice: 'Summe netto',
|
||||
unitNetPrice: 'Einheit netto',
|
||||
unitType: 'Einheit',
|
||||
yourCustomerId: 'Ihre Kundennummer:',
|
||||
yourVatId: 'Ihre Umsatzsteuer-ID:',
|
||||
continuesOnPage: 'Fortsetzung auf Seite',
|
||||
finalPageStatement: 'Dies ist die letzte Seite dieses Dokuments.',
|
||||
page: 'Seite',
|
||||
vatShort: 'USt',
|
||||
export const DE_translations: Dictionary = {
|
||||
address: "Adresse",
|
||||
"bank.accountHolder": "Kontoinhaber",
|
||||
"bank.bic": "BIC",
|
||||
"bank.iban": "IBAN",
|
||||
"bank.institution": "Bankinstitut",
|
||||
"bankConnection@@title": "Bankverbindung",
|
||||
"contact@@title": "Kontaktinformationen",
|
||||
"customer.number": "Ihre Kundennummer",
|
||||
description: "Beschreibung",
|
||||
"empty.logo": "Kein Logo gesetzt",
|
||||
"empty.number.customer": "nicht registriert",
|
||||
empty: "nicht angegeben",
|
||||
fax: "Fax",
|
||||
introStatement:
|
||||
"Wir stellen Ihnen hiermit folgende Produkte und Dienstleistungen in Rechnung",
|
||||
"invoice.number": "Rechnungsnr.",
|
||||
invoice: "Rechnung",
|
||||
"item.position": "Pos.",
|
||||
mail: "E-Mail",
|
||||
"overlay@@draft": "Entwurf",
|
||||
"page.continueNext": "Fortsetzung auf Seite",
|
||||
"page.final": "Dies ist die letzte Seite dieses Dokuments.",
|
||||
page: "Seite",
|
||||
pageOf: "von",
|
||||
"payment.qr": "Überweisen per QR-Code",
|
||||
"payment.qr.description":
|
||||
"Den QR-Code einfach mit der Banking-App einscannen",
|
||||
"payment.terms": "Zahlungsbedingungen",
|
||||
"payment.terms.direct": "Ohne Abzug bis zum",
|
||||
"periodOfPerformance.day": "Lieferdatum",
|
||||
"periodOfPerformance.range": "Lieferzeitraum",
|
||||
phone: "Telefon",
|
||||
"price.total.net": "Gesamtpreis",
|
||||
"price.unit.net": "Stückpreis",
|
||||
price: "Preis",
|
||||
quantity: "Menge",
|
||||
referencedContract: "Referenzierter Vertrag",
|
||||
"referencedContract.text":
|
||||
"Diese Rechnung bezieht sich auf die getroffenen Vertragsvereinbarungen vom",
|
||||
"registration.label": "Registrierungsinfo",
|
||||
subject: "Betreff",
|
||||
sum: "Summe",
|
||||
totalGross: "Gesamtbetrag brutto",
|
||||
"unit.type": "Einheit",
|
||||
"vat.position": "auf Positionen",
|
||||
"vat.reverseCharge.note":
|
||||
"Die Umsatzsteuer entsteht im Reverse-Charge-Verfahren und ist vom Kunden zu zahlen.",
|
||||
"vat.short": "MwSt.",
|
||||
"vat.yourId": "Ihre hinterlegte USt-Id",
|
||||
vat: "Umsatzsteuer",
|
||||
};
|
||||
|
||||
// Define Spanish translations
|
||||
export const ES_translations: TTranslationImplementation = {
|
||||
address: 'Dirección',
|
||||
bankConnection: 'Conexión bancaria',
|
||||
contactInfo: 'Información de contacto',
|
||||
description: 'Descripción',
|
||||
invoice: 'Factura',
|
||||
itemPos: 'Pos.',
|
||||
quantity: 'Cantidad',
|
||||
registrationInfo: 'Información de registro',
|
||||
reverseVatNote: 'El IVA se aplica por inversión del sujeto pasivo y debe ser pagado por el cliente.',
|
||||
totalNetPrice: 'Precio total neto',
|
||||
unitNetPrice: 'Precio unitario neto',
|
||||
unitType: 'Tipo de unidad',
|
||||
yourCustomerId: 'Su número de cliente:',
|
||||
yourVatId: 'Su ID de IVA:',
|
||||
continuesOnPage: 'Continúa en la página',
|
||||
finalPageStatement: 'Esta es la última página de este documento.',
|
||||
page: 'Página',
|
||||
vatShort: 'IVA',
|
||||
};
|
||||
// export const ES_translations: TTranslationImplementation = {
|
||||
// address: "Dirección",
|
||||
// bankConnection: "Conexión bancaria",
|
||||
// contactInfo: "Información de contacto",
|
||||
// description: "Descripción",
|
||||
// invoice: "Factura",
|
||||
// itemPos: "Pos.",
|
||||
// quantity: "Cantidad",
|
||||
// registrationInfo: "Información de registro",
|
||||
// reverseVatNote:
|
||||
// "El IVA se aplica por inversión del sujeto pasivo y debe ser pagado por el cliente.",
|
||||
// totalNetPrice: "Precio total neto",
|
||||
// unitNetPrice: "Precio unitario neto",
|
||||
// unitType: "Tipo de unidad",
|
||||
// yourCustomerId: "Su número de cliente:",
|
||||
// yourVatId: "Su ID de IVA:",
|
||||
// continuesOnPage: "Continúa en la página",
|
||||
// finalPageStatement: "Esta es la última página de este documento.",
|
||||
// page: "Página",
|
||||
// vatShort: "IVA",
|
||||
// };
|
||||
|
||||
// Define French translations
|
||||
export const FR_translations: TTranslationImplementation = {
|
||||
address: 'Adresse',
|
||||
bankConnection: 'Coordonnées bancaires',
|
||||
contactInfo: 'Informations de contact',
|
||||
description: 'Description',
|
||||
invoice: 'Facture',
|
||||
itemPos: 'Position',
|
||||
quantity: 'Quantité',
|
||||
registrationInfo: "Informations d'enregistrement",
|
||||
reverseVatNote:
|
||||
"La TVA s'applique selon le mécanisme d'autoliquidation et est à payer par le client.",
|
||||
totalNetPrice: 'Prix net total',
|
||||
unitNetPrice: 'Prix unitaire net',
|
||||
unitType: "Type d'unité",
|
||||
yourCustomerId: 'Votre numéro de client :',
|
||||
yourVatId: 'Votre numéro de TVA :',
|
||||
continuesOnPage: 'Continue sur la page',
|
||||
finalPageStatement: 'Ceci est la dernière page de ce document.',
|
||||
page: 'Page',
|
||||
vatShort: 'TVA',
|
||||
};
|
||||
// export const FR_translations: TTranslationImplementation = {
|
||||
// address: "Adresse",
|
||||
// bankConnection: "Coordonnées bancaires",
|
||||
// contactInfo: "Informations de contact",
|
||||
// description: "Description",
|
||||
// invoice: "Facture",
|
||||
// itemPos: "Position",
|
||||
// quantity: "Quantité",
|
||||
// registrationInfo: "Informations d'enregistrement",
|
||||
// reverseVatNote:
|
||||
// "La TVA s'applique selon le mécanisme d'autoliquidation et est à payer par le client.",
|
||||
// totalNetPrice: "Prix net total",
|
||||
// unitNetPrice: "Prix unitaire net",
|
||||
// unitType: "Type d'unité",
|
||||
// yourCustomerId: "Votre numéro de client :",
|
||||
// yourVatId: "Votre numéro de TVA :",
|
||||
// continuesOnPage: "Continue sur la page",
|
||||
// finalPageStatement: "Ceci est la dernière page de ce document.",
|
||||
// page: "Page",
|
||||
// vatShort: "TVA",
|
||||
// };
|
||||
|
||||
// Define Italian translations
|
||||
export const IT_translations: TTranslationImplementation = {
|
||||
address: 'Indirizzo',
|
||||
bankConnection: 'Coordinate bancarie',
|
||||
contactInfo: 'Informazioni di contatto',
|
||||
description: 'Descrizione',
|
||||
invoice: 'Fattura',
|
||||
itemPos: 'Pos.',
|
||||
quantity: 'Quantità',
|
||||
registrationInfo: 'Informazioni di registrazione',
|
||||
reverseVatNote: "L'IVA è applicata con inversione contabile ed è a carico del cliente.",
|
||||
totalNetPrice: 'Prezzo netto totale',
|
||||
unitNetPrice: 'Prezzo netto unitario',
|
||||
unitType: 'Tipo di unità',
|
||||
yourCustomerId: 'Il tuo numero cliente:',
|
||||
yourVatId: 'Il tuo numero di partita IVA:',
|
||||
continuesOnPage: 'Continua alla pagina',
|
||||
finalPageStatement: 'Questa è l\'ultima pagina di questo documento.',
|
||||
page: 'Pagina',
|
||||
vatShort: 'IVA',
|
||||
};
|
||||
// export const IT_translations: TTranslationImplementation = {
|
||||
// address: "Indirizzo",
|
||||
// bankConnection: "Coordinate bancarie",
|
||||
// contactInfo: "Informazioni di contatto",
|
||||
// description: "Descrizione",
|
||||
// invoice: "Fattura",
|
||||
// itemPos: "Pos.",
|
||||
// quantity: "Quantità",
|
||||
// registrationInfo: "Informazioni di registrazione",
|
||||
// reverseVatNote:
|
||||
// "L'IVA è applicata con inversione contabile ed è a carico del cliente.",
|
||||
// totalNetPrice: "Prezzo netto totale",
|
||||
// unitNetPrice: "Prezzo netto unitario",
|
||||
// unitType: "Tipo di unità",
|
||||
// yourCustomerId: "Il tuo numero cliente:",
|
||||
// yourVatId: "Il tuo numero di partita IVA:",
|
||||
// continuesOnPage: "Continua alla pagina",
|
||||
// finalPageStatement: "Questa è l'ultima pagina di questo documento.",
|
||||
// page: "Pagina",
|
||||
// vatShort: "IVA",
|
||||
// };
|
||||
|
||||
// Language Code Map
|
||||
export const languageCodeMap: Record<string, TTranslationImplementation> = {
|
||||
export const languageCodeMap: Record<string, Dictionary> = {
|
||||
EN: EN_translations,
|
||||
DE: DE_translations,
|
||||
ES: ES_translations,
|
||||
FR: FR_translations,
|
||||
IT: IT_translations,
|
||||
// ES: ES_translations,
|
||||
// FR: FR_translations,
|
||||
// IT: IT_translations,
|
||||
};
|
||||
|
||||
// Language Code Type
|
||||
export type TLanguageCode = keyof typeof languageCodeMap;
|
||||
export type LanguageCode = keyof typeof languageCodeMap;
|
||||
|
||||
function* getTranslationKeyHierarchy(
|
||||
key: TranslationKey
|
||||
): Generator<TranslationKey, TranslationKey> {
|
||||
yield key;
|
||||
|
||||
const areaSplit = key.split("@@") as [TranslationKey, TranslationKey];
|
||||
let rest = areaSplit[1];
|
||||
|
||||
if (rest) {
|
||||
yield rest;
|
||||
} else {
|
||||
rest = areaSplit[0];
|
||||
}
|
||||
|
||||
if (!rest.includes(".")) return;
|
||||
|
||||
const parts = rest.split(".");
|
||||
for (let i = parts.length - 1; i > 0; i--) {
|
||||
yield parts.slice(0, i).join(".") as TranslationKey;
|
||||
}
|
||||
}
|
||||
|
||||
// Translate Function
|
||||
export const translate = (
|
||||
languageCode: TLanguageCode,
|
||||
key: TTranslationKey,
|
||||
defaultValue: string
|
||||
languageCode: LanguageCode,
|
||||
key: TranslationKey
|
||||
): string => {
|
||||
const translations = languageCodeMap[languageCode] || EN_translations;
|
||||
return translations[key] || defaultValue;
|
||||
};
|
||||
const dictionary = languageCodeMap[languageCode] || EN_translations;
|
||||
const lookupHierarchy = getTranslationKeyHierarchy(key);
|
||||
|
||||
let found: string;
|
||||
|
||||
for (let keyOption of lookupHierarchy) {
|
||||
found = dictionary[keyOption] || EN_translations[keyOption];
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
};
|
||||
|
Reference in New Issue
Block a user