273 lines
8.3 KiB
TypeScript
273 lines
8.3 KiB
TypeScript
// Define English translations without enforcing TTranslationImplementation yet
|
|
export const EN_translations = {
|
|
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
|
|
|
|
/**
|
|
* 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 Dictionary = {
|
|
[key in TranslationKey]: string;
|
|
};
|
|
|
|
// Define German translations
|
|
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",
|
|
// };
|
|
|
|
// 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",
|
|
// };
|
|
|
|
// 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",
|
|
// };
|
|
|
|
// Language Code Map
|
|
export const languageCodeMap: Record<string, Dictionary> = {
|
|
EN: EN_translations,
|
|
DE: DE_translations,
|
|
// ES: ES_translations,
|
|
// FR: FR_translations,
|
|
// IT: IT_translations,
|
|
};
|
|
|
|
// Language Code Type
|
|
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: LanguageCode,
|
|
key: TranslationKey
|
|
): string => {
|
|
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;
|
|
};
|