mirror of
https://github.com/spliit-app/spliit.git
synced 2026-02-14 19:46:12 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8742bd59da | ||
|
|
8eea062218 | ||
|
|
9a5674e239 | ||
|
|
50b3a2e431 | ||
|
|
e8d46cd4f3 | ||
|
|
8f896f7412 | ||
|
|
504631454a | ||
|
|
345f3716c9 | ||
|
|
5fff8da08d | ||
|
|
07e24f7fcb |
18
jest.config.ts
Normal file
18
jest.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { Config } from 'jest'
|
||||
import nextJest from 'next/jest.js'
|
||||
|
||||
const createJestConfig = nextJest({
|
||||
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
|
||||
dir: './',
|
||||
})
|
||||
|
||||
// Add any custom config to be passed to Jest
|
||||
const config: Config = {
|
||||
coverageProvider: 'v8',
|
||||
testEnvironment: 'jsdom',
|
||||
// Add more setup options before each test is run
|
||||
// setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
|
||||
}
|
||||
|
||||
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
|
||||
export default createJestConfig(config)
|
||||
396
messages/de-DE.json
Normal file
396
messages/de-DE.json
Normal file
@@ -0,0 +1,396 @@
|
||||
{
|
||||
"Homepage": {
|
||||
"title": "Teile <strong>Ausgaben</strong> mit <strong>Freunden & Familie</strong>",
|
||||
"description": "Willkommen zu deiner neuen <strong>Spliit</strong>-Instanz!",
|
||||
"button": {
|
||||
"groups": "Zu den Gruppen",
|
||||
"github": "GitHub"
|
||||
}
|
||||
},
|
||||
"Header": {
|
||||
"groups": "Gruppen"
|
||||
},
|
||||
"Footer": {
|
||||
"madeIn": "Entwickelt in Montréal, Québec 🇨🇦",
|
||||
"builtBy": "Erstellt von <author>Sebastien Castiel</author> und <source>Mitwirkenden</source>"
|
||||
},
|
||||
"Expenses": {
|
||||
"title": "Ausgaben",
|
||||
"description": "Hier sind die Ausgaben, die du für deine Gruppe erstellt hast.",
|
||||
"create": "Ausgabe hinzufügen",
|
||||
"createFirst": "Erstelle die Erste",
|
||||
"noExpenses": "Deine Gruppe hat noch keine Ausgaben.",
|
||||
"exportJson": "Als JSON exportieren",
|
||||
"searchPlaceholder": "Suche nach einer Ausgabe…",
|
||||
"ActiveUserModal": {
|
||||
"title": "Wer bist du?",
|
||||
"description": "Sag uns, welcher Teilnehmer du bist, um die angezeigten Informationen auf dich anzupassen.",
|
||||
"nobody": "Ich will niemanden auswählen",
|
||||
"save": "Änderungen speichern",
|
||||
"footer": "Diese Einstellung kann später in den Gruppeneinstellungen geändert werden."
|
||||
},
|
||||
"Groups": {
|
||||
"upcoming": "Bevorstehend",
|
||||
"thisWeek": "Diese Woche",
|
||||
"earlierThisMonth": "Diesen Monat",
|
||||
"lastMonth": "Letzten Monat",
|
||||
"earlierThisYear": "Dieses Jahr",
|
||||
"lastYera": "Letztes Jahr",
|
||||
"older": "Älter"
|
||||
}
|
||||
},
|
||||
"ExpenseCard": {
|
||||
"paidBy": "Gezahlt von <strong>{paidBy}</strong> für <paidFor></paidFor>",
|
||||
"receivedBy": "Empfangen von <strong>{paidBy}</strong> für <paidFor></paidFor>",
|
||||
"yourBalance": "Deine Bilanz:"
|
||||
},
|
||||
"Groups": {
|
||||
"myGroups": "Meine Gruppen",
|
||||
"create": "Erstellen",
|
||||
"loadingRecent": "Lade letzte Gruppen…",
|
||||
"NoRecent": {
|
||||
"description": "Du hast in der letzten Zeit keine Gruppe besucht.",
|
||||
"create": "Erstelle eine",
|
||||
"orAsk": "oder bitte einen Freund, dir einen Link zu einer Existierenden zu schicken."
|
||||
},
|
||||
"recent": "Letzte Gruppen",
|
||||
"starred": "Favorisierte Gruppen",
|
||||
"archived": "Archivierte Gruppen",
|
||||
"archive": "Gruppe archivieren",
|
||||
"unarchive": "Gruppe wiederherstellen",
|
||||
"removeRecent": "Aus letzten Gruppen entfernen",
|
||||
"RecentRemovedToast": {
|
||||
"title": "Gruppe wurde entfernt",
|
||||
"description": "Die Gruppe wurde von deiner Liste der letzten Gruppen entfernt.",
|
||||
"undoAlt": "Gruppe entfernen rückgängig machen",
|
||||
"undo": "Rückgängig machen"
|
||||
},
|
||||
"AddByURL": {
|
||||
"button": "Mit URL hinzufügen",
|
||||
"title": "Gruppe mit URL hinzufügen",
|
||||
"description": "Wenn eine Gruppe mit dir geteilt wurde, kannst du ihre URL hier einfügen, um sie zu deiner Liste hinzuzufügen.",
|
||||
"error": "Ups, wir können die Gruppe mit der angegebenen URL nicht finden…"
|
||||
},
|
||||
"NotFound": {
|
||||
"text": "Diese Gruppe existiert nicht.",
|
||||
"link": "Gehe zu zuletzt besuchten Gruppen"
|
||||
}
|
||||
},
|
||||
"GroupForm": {
|
||||
"title": "Gruppeninformationen",
|
||||
"NameField": {
|
||||
"label": "Gruppenname",
|
||||
"placeholder": "Sommerurlaub",
|
||||
"description": "Gib deiner Gruppe einen Namen."
|
||||
},
|
||||
"InformationField": {
|
||||
"label": "Gruppeninformationen",
|
||||
"placeholder": "Welche Informationen sind relevant für Gruppenmitglieder?"
|
||||
},
|
||||
"CurrencyField": {
|
||||
"label": "Währungssymbol",
|
||||
"placeholder": "€, $, £…",
|
||||
"description": "Wir benutzen es, um Beträge anzuzeigen."
|
||||
},
|
||||
"Participants": {
|
||||
"title": "Mitglieder",
|
||||
"description": "Füge einen Namen für jedes Gruppenmitglied hinzu.",
|
||||
"protectedParticipant": "Dieses Mitglied ist Teil der Ausgaben und kann nicht entfernt werden.",
|
||||
"new": "Neu",
|
||||
"add": "Mitglied hinzufügen",
|
||||
"John": "Johannes",
|
||||
"Jane": "Janina",
|
||||
"Jack": "Jakob"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Lokale Einstellungen",
|
||||
"description": "Dies sind Einstellungen pro Gerät, die verwendet werden, um deine Benutzererfahrung zu verbessern.",
|
||||
"ActiveUserField": {
|
||||
"label": "Aktiver Nutzer",
|
||||
"placeholder": "Wähle ein Mitglied",
|
||||
"none": "Keiner",
|
||||
"description": "Standardnutzer, der die Ausgaben übernimmt."
|
||||
},
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert…",
|
||||
"create": "Erstellen",
|
||||
"creating": "Erstellt…",
|
||||
"cancel": "Abbrechen"
|
||||
}
|
||||
},
|
||||
"ExpenseForm": {
|
||||
"Income": {
|
||||
"create": "Einnahme erstellen",
|
||||
"edit": "Einnahme bearbeiten",
|
||||
"TitleField": {
|
||||
"label": "Titel der Einnahme",
|
||||
"placeholder": "Montagabend Restaurant",
|
||||
"description": "Füge eine Beschreibung für die Einnahme hinzu."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Datum der Einnahme",
|
||||
"description": "Füge ein Datum hinzu für wann die Einnahme erhalten wurde."
|
||||
},
|
||||
"categoryFieldDescription": "Wähle die Kategorie der Einnahme.",
|
||||
"paidByField": {
|
||||
"label": "Empfangen von",
|
||||
"description": "Wähle das Mitglied, das die Einnahme erhalten hat."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Empfangen für",
|
||||
"description": "Wähle für wen die Einnahme empfangen wurde."
|
||||
},
|
||||
"splitModeDescription": "Wähle, wie die Einnahme aufgeteilt werden soll.",
|
||||
"attachDescription": "Füge der Einnahme einen Beleg hinzu."
|
||||
},
|
||||
"Expense": {
|
||||
"create": "Augabe erstellen",
|
||||
"edit": "Ausgabe bearbeiten",
|
||||
"TitleField": {
|
||||
"label": "Titel der Ausgabe",
|
||||
"placeholder": "Montagabend Restaurant",
|
||||
"description": "Füge eine Beschreibung für die Ausgabe hinzu."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Datum der Ausgabe",
|
||||
"description": "Füge das Datum ein, zu dem die Ausgabe getätigt wurde."
|
||||
},
|
||||
"categoryFieldDescription": "Wähle eine Kategorie für die Ausgabe.",
|
||||
"paidByField": {
|
||||
"label": "Gezahlt von",
|
||||
"description": "Wähle das Mitglied, das die Ausgabe bezahlt hat."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Gezahlt für",
|
||||
"description": "Wähle für wen die Ausgabe gezahlt wurde."
|
||||
},
|
||||
"splitModeDescription": "Wähle, wie die Ausgabe aufgeteilt werden soll.",
|
||||
"attachDescription": "Füge der Ausgabe einen Beleg hinzu."
|
||||
},
|
||||
"amountField": {
|
||||
"label": "Betrag"
|
||||
},
|
||||
"isReimbursementField": {
|
||||
"label": "Das ist eine Rückzahlung"
|
||||
},
|
||||
"categoryField": {
|
||||
"label": "Kategorie"
|
||||
},
|
||||
"notesField": {
|
||||
"label": "Notizen"
|
||||
},
|
||||
"selectNone": "Keine auswählen",
|
||||
"selectAll": "Alle auswählen",
|
||||
"shares": "Anteil(e)",
|
||||
"advancedOptions": "Fortgeschrittene Aufteilungsoptionen…",
|
||||
"SplitModeField": {
|
||||
"label": "Aufteilungsart",
|
||||
"evenly": "Gleich verteilt",
|
||||
"byShares": "Ungleich – Nach Anteilen",
|
||||
"byPercentage": "Ungleich – Prozentual",
|
||||
"byAmount": "Ungleich – Nach Betrag",
|
||||
"saveAsDefault": "Als Standardoptionen zur Aufteilung speichern"
|
||||
},
|
||||
"DeletePopup": {
|
||||
"label": "Löschen",
|
||||
"title": "Diese Ausgabe löschen?",
|
||||
"description": "Willst du diese Ausgabe wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"yes": "Ja",
|
||||
"cancel": "Abbrechen"
|
||||
},
|
||||
"attachDocuments": "Dokument hinzufügen",
|
||||
"create": "Erstellen",
|
||||
"creating": "Erstellt…",
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert…",
|
||||
"cancel": "Abbrechen"
|
||||
},
|
||||
"ExpenseDocumentsInput": {
|
||||
"TooBigToast": {
|
||||
"title": "Die Datei ist zu groß",
|
||||
"description": "Die maximale Dateigröße ist {maxSize}. Deine ist ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Fehler beim Hochladen der Datei",
|
||||
"description": "Beim Hochladen der Datei ist etwas schiefgelaufen. Versuche es später nochmal oder wähle eine andere Datei.",
|
||||
"retry": "Wiederholen"
|
||||
}
|
||||
},
|
||||
"CreateFromReceipt": {
|
||||
"Dialog": {
|
||||
"triggerTitle": "Ausgabe von Rechnungsbeleg erstellen",
|
||||
"title": "Von Rechnungsbeleg erstellen",
|
||||
"description": "Ausgabeninformationen von einem Foto einer Rechnung lesen.",
|
||||
"body": "Lade ein Foto der Rechnung hoch und wir versuchen die Ausgabeinformationen zu extrahieren",
|
||||
"selectImage": "Bild wählen…",
|
||||
"titleLabel": "Titel:",
|
||||
"categoryLabel": "Kategorie:",
|
||||
"amountLabel": "Betrag:",
|
||||
"dateLabel": "Datum:",
|
||||
"editNext": "Als nächstes kannst du die Informationen zur Ausgabe editieren.",
|
||||
"continue": "Weiter"
|
||||
},
|
||||
"unknown": "Unbekannt",
|
||||
"TooBigToast": {
|
||||
"title": "Die Datei ist zu groß",
|
||||
"description": "Die maximale Dateigröße ist {maxSize}. Deine ist ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Fehler beim Hochladen der Datei",
|
||||
"description": "Beim Hochladen der Datei ist etwas schiefgelaufen. Versuche es später nochmal oder wähle eine andere Datei.",
|
||||
"retry": "Wiederholen"
|
||||
}
|
||||
},
|
||||
"Balances": {
|
||||
"title": "Bilanz",
|
||||
"description": "Das sind die Beträge, die jedes Mitglied bezahlt oder empfangen hat.",
|
||||
"Reimbursements": {
|
||||
"title": "Vorgeschlagene Rückzahlungen",
|
||||
"description": "Hier sind Vorschläge für optimierte Rückzahlungen zwischen Mitgliedern.",
|
||||
"noImbursements": "Es sieht aus, als seien in der Gruppe keine Rückzahlungen nötig 😁",
|
||||
"owes": "<strong>{from}</strong> schuldet <strong>{to}</strong>",
|
||||
"markAsPaid": "Als gezahlt markieren"
|
||||
}
|
||||
},
|
||||
"Stats": {
|
||||
"title": "Statistiken",
|
||||
"Totals": {
|
||||
"title": "Gesamtausgaben",
|
||||
"description": "Zusammenfassung der Ausgaben der gesamten Gruppe.",
|
||||
"groupSpendings": "Gesamte Ausgaben der Gruppe",
|
||||
"groupEarnings": "Gesamte Einnahmen der Gruppe",
|
||||
"yourSpendings": "Deine gesamten Ausgaben",
|
||||
"yourEarnings": "Deine gesamten Einnahmen",
|
||||
"yourShare": "Dein gesamter Anteil"
|
||||
}
|
||||
},
|
||||
"Activity": {
|
||||
"title": "Aktivitäten",
|
||||
"description": "Zusammenfassung aller Aktivitäten in dieser Gruppe.",
|
||||
"noActivity": "Es gab noch keine Aktivität in dieser Gruppe.",
|
||||
"someone": "Jemand",
|
||||
"settingsModified": "Die Gruppeneinstellungen wurden von <strong>{participant}</strong> verändert.",
|
||||
"expenseCreated": "Augabe <em>{expense}</em> wurde von <strong>{participant}</strong> erstellt.",
|
||||
"expenseUpdated": "Ausgabe <em>{expense}</em> wurde von <strong>{participant}</strong> aktualisiert.",
|
||||
"expenseDeleted": "Ausgabe <em>{expense}</em> wurde von <strong>{participant}</strong> gelöscht.",
|
||||
"Groups": {
|
||||
"today": "Heute",
|
||||
"yesterday": "Gestern",
|
||||
"earlierThisWeek": "Diese Woche",
|
||||
"lastWeek": "Letze Woche",
|
||||
"earlierThisMonth": "Diesen Monat",
|
||||
"lastMonth": "Letzen Monat",
|
||||
"earlierThisYear": "Dieses Jahr",
|
||||
"lastYear": "Letztes Jahr",
|
||||
"older": "Älter"
|
||||
}
|
||||
},
|
||||
"Information": {
|
||||
"title": "Informationen",
|
||||
"description": "Nutze diesen Ort, um Informationen hinzuzufügen, die für die Gruppenmitglieder wichtig sein könnten.",
|
||||
"empty": "Noch keine Gruppeninformationen vorhanden."
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Einstellungen"
|
||||
},
|
||||
"Locale": {
|
||||
"en-US": "English",
|
||||
"fi": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"es": "Español",
|
||||
"de-DE": "Deutsch",
|
||||
"zh-CN": "Chinese (Simplified)",
|
||||
"ru-RU": "Русский"
|
||||
},
|
||||
"Share": {
|
||||
"title": "Teilen",
|
||||
"description": "Teile die URL, damit andere Mitglieder die Gruppe sehen und Ausgaben hinzufügen können.",
|
||||
"warning": "Achtung!",
|
||||
"warningHelp": "Jede person mit der Gruppen-URL kann Ausgaben sehen und editieren. Teile den Link mit Bedacht!"
|
||||
},
|
||||
"SchemaErrors": {
|
||||
"min1": "Gib mindestens ein Zeichen ein.",
|
||||
"min2": "Gib mindestens zwei Zeichen ein.",
|
||||
"max5": "Gib maximal fünf Zeichen ein.",
|
||||
"max50": "Gib maximal 50 Zeichen ein.",
|
||||
"duplicateParticipantName": "Der Name ist bereits an ein anderes Gruppenmitglied vergeben.",
|
||||
"titleRequired": "Bitte gib einen Titel an.",
|
||||
"invalidNumber": "Zahl nicht valide.",
|
||||
"amountRequired": "Du musst einen Betrag angeben.",
|
||||
"amountNotZero": "Der Betrag darf nicht 0 sein.",
|
||||
"amountTenMillion": "Der Betrag muss kleiner als 10.000.000 sein",
|
||||
"paidByRequired": "Du musst ein Mitglied auswählen.",
|
||||
"paidForMin1": "Die Ausgabe muss mindestens für ein Mitglied bezahlt werden.",
|
||||
"noZeroShares": "Alle Anteile müssen größer als 0 sein.",
|
||||
"amountSum": "Die Summe der Beträge muss dem Betrag der Ausgabe entsprechen.",
|
||||
"percentageSum": "Die Summe der prozentualen Anteile muss 100 ergeben."
|
||||
},
|
||||
"Categories": {
|
||||
"search": "Nach Kategorie suchen...",
|
||||
"noCategory": "Keine Kategorie gefunden.",
|
||||
"Uncategorized": {
|
||||
"heading": "Nicht kategorisiert",
|
||||
"General": "Allgemein",
|
||||
"Payment": "Zahlung"
|
||||
},
|
||||
"Entertainment": {
|
||||
"heading": "Vergnügen",
|
||||
"Entertainment": "Vergnügen",
|
||||
"Games": "Spiele",
|
||||
"Movies": "Filme",
|
||||
"Music": "Musik",
|
||||
"Sports": "Sport"
|
||||
},
|
||||
"Food and Drink": {
|
||||
"heading": "Essen und Trinken",
|
||||
"Food and Drink": "Essen und Trinken",
|
||||
"Dining Out": "Essen gehen",
|
||||
"Groceries": "Lebensmittel",
|
||||
"Liquor": "Alkohol"
|
||||
},
|
||||
"Home": {
|
||||
"heading": "Zuhause",
|
||||
"Home": "Zuhause",
|
||||
"Electronics": "Elektronik",
|
||||
"Furniture": "Möbel",
|
||||
"Household Supplies": "Haushaltsgegenstände",
|
||||
"Maintenance": "Wartung",
|
||||
"Mortgage": "Hypothek",
|
||||
"Pets": "Haustiere",
|
||||
"Rent": "Miete",
|
||||
"Services": "Dienstleistungen"
|
||||
},
|
||||
"Life": {
|
||||
"heading": "Leben",
|
||||
"Childcare": "Kinderversorgung",
|
||||
"Clothing": "Kleidung",
|
||||
"Education": "Bildung",
|
||||
"Gifts": "Geschenke",
|
||||
"Insurance": "Versicherung",
|
||||
"Medical Expenses": "Medizinische Ausgaben",
|
||||
"Taxes": "Steuern"
|
||||
},
|
||||
"Transportation": {
|
||||
"heading": "Transport",
|
||||
"Transportation": "Transport",
|
||||
"Bicycle": "Fahrrad",
|
||||
"Bus/Train": "Bus/Bahn",
|
||||
"Car": "Auto",
|
||||
"Gas/Fuel": "Tanken",
|
||||
"Hotel": "Hotel",
|
||||
"Parking": "Parken",
|
||||
"Plane": "Flugzeug",
|
||||
"Taxi": "Taxi"
|
||||
},
|
||||
"Utilities": {
|
||||
"heading": "Versorgung",
|
||||
"Utilities": "Versorgung",
|
||||
"Cleaning": "Reinigung/Putzen",
|
||||
"Electricity": "Strom",
|
||||
"Heat/Gas": "Heizung",
|
||||
"Trash": "Müll",
|
||||
"TV/Phone/Internet": "TV/Internet/Telefonie",
|
||||
"Water": "Wasser"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
{
|
||||
"Homepage": {
|
||||
"title": "Share <strong>Expenses</strong> with <strong>Friends & Family</strong>",
|
||||
"description": "Welcome to your new <strong>Spliit</strong> instance !",
|
||||
"button": {
|
||||
"groups": "Go to groups",
|
||||
"github": "GitHub"
|
||||
}
|
||||
},
|
||||
"Header": {
|
||||
"groups": "Groups"
|
||||
},
|
||||
@@ -287,7 +295,12 @@
|
||||
},
|
||||
"Locale": {
|
||||
"en-US": "English",
|
||||
"fi": "Suomi"
|
||||
"fi": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"es": "Español",
|
||||
"de-DE": "Deutsch",
|
||||
"zh-CN": "Chinese (Simplified)",
|
||||
"ru-RU": "Русский"
|
||||
},
|
||||
"Share": {
|
||||
"title": "Share",
|
||||
|
||||
396
messages/es.json
Normal file
396
messages/es.json
Normal file
@@ -0,0 +1,396 @@
|
||||
{
|
||||
"Homepage": {
|
||||
"title": "Comparte <strong>Gastos</strong> con <strong>Amigos y Familia</strong>",
|
||||
"description": "¡Bienvenido a tu nueva instancia de <strong>Spliit</strong>!",
|
||||
"button": {
|
||||
"groups": "Ir a grupos",
|
||||
"github": "GitHub"
|
||||
}
|
||||
},
|
||||
"Header": {
|
||||
"groups": "Grupos"
|
||||
},
|
||||
"Footer": {
|
||||
"madeIn": "Hecho en Montréal, Québec 🇨🇦",
|
||||
"builtBy": "Construido por <author>Sebastien Castiel</author> y <source>colaboradores</source>"
|
||||
},
|
||||
"Expenses": {
|
||||
"title": "Gastos",
|
||||
"description": "Aqui encontraras los gastos que has creado para tu grupo.",
|
||||
"create": "Crear gasto",
|
||||
"createFirst": "Crea el primero",
|
||||
"noExpenses": "Tu grupo aun no tiene gastos.",
|
||||
"exportJson": "Exportar a JSON",
|
||||
"searchPlaceholder": "Busca un gasto…",
|
||||
"ActiveUserModal": {
|
||||
"title": "¿Quién es usted?",
|
||||
"description": "Dinos qué participante eres para que podamos personalizar cómo se muestra la información.",
|
||||
"nobody": "No quiero seleccionar a nadie",
|
||||
"save": "Guardar cambios",
|
||||
"footer": "Esta configuración puede modificarse posteriormente en los ajustes del grupo."
|
||||
},
|
||||
"Groups": {
|
||||
"upcoming": "Próximamente",
|
||||
"thisWeek": "Esta semana",
|
||||
"earlierThisMonth": "A principios de este mes",
|
||||
"lastMonth": "El mes pasado",
|
||||
"earlierThisYear": "A principios de este año",
|
||||
"lastYera": "El año pasado",
|
||||
"older": "Más antiguos"
|
||||
}
|
||||
},
|
||||
"ExpenseCard": {
|
||||
"paidBy": "Pagado por <strong>{paidBy}</strong> para <paidFor></paidFor>",
|
||||
"receivedBy": "Recibido por <strong>{paidBy}</strong> para <paidFor></paidFor>",
|
||||
"yourBalance": "Tu balance:"
|
||||
},
|
||||
"Groups": {
|
||||
"myGroups": "Mis grupos",
|
||||
"create": "Crear",
|
||||
"loadingRecent": "Cargando grupos recientes…",
|
||||
"NoRecent": {
|
||||
"description": "No has visitado ningun grupo recientemente.",
|
||||
"create": "Crea uno",
|
||||
"orAsk": "o pídele a un amigo que te envíe el enlace a uno ya existente.."
|
||||
},
|
||||
"recent": "Grupos recientes",
|
||||
"starred": "Grupos favoritos",
|
||||
"archived": "Grupos archivados",
|
||||
"archive": "Archivar grupo",
|
||||
"unarchive": "Desarchivar groupo",
|
||||
"removeRecent": "Remove from recent groups",
|
||||
"RecentRemovedToast": {
|
||||
"title": "El grupo fue eliminado",
|
||||
"description": "El grupo ha sido eliminado de tu lista de grupos recientes.",
|
||||
"undoAlt": "Deshacer la eliminación del grupo",
|
||||
"undo": "Deshacer"
|
||||
},
|
||||
"AddByURL": {
|
||||
"button": "Añadir mediante url",
|
||||
"title": "Añadir grupo mediante url",
|
||||
"description": "Si te han compartido un grupo, puedes pegar aquí su URL para añadirlo a tu lista.",
|
||||
"error": "Oops, no somos capaces de encontrar el grupo desde la URL que has proporcionado..."
|
||||
},
|
||||
"NotFound": {
|
||||
"text": "Este grupo no existe.",
|
||||
"link": "Ir a los últimos grupos visitados"
|
||||
}
|
||||
},
|
||||
"GroupForm": {
|
||||
"title": "Información del grupo",
|
||||
"NameField": {
|
||||
"label": "Nombre del grupo",
|
||||
"placeholder": "Vacaciones en Barcelona",
|
||||
"description": "Inserta un nombre para tu nuevo grupo."
|
||||
},
|
||||
"InformationField": {
|
||||
"label": "Información del grupo",
|
||||
"placeholder": "Qué información es relevante para los participantes del grupo?"
|
||||
},
|
||||
"CurrencyField": {
|
||||
"label": "Símbolo de divisa",
|
||||
"placeholder": "$, €, £…",
|
||||
"description": "Lo usaremos para mostrar balances."
|
||||
},
|
||||
"Participants": {
|
||||
"title": "Participantes",
|
||||
"description": "Ingresa el nombre de cada participante.",
|
||||
"protectedParticipant": "Estos participantes forman parte de gastos y no pueden ser eliminados.",
|
||||
"new": "Nuevo",
|
||||
"add": "Añadir participante",
|
||||
"John": "Juan",
|
||||
"Jane": "Maria",
|
||||
"Jack": "Sergio"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Ajustes locales",
|
||||
"description": "Estos ajustes se establecen por dispositivo y se utilizan para personalizar su experiencia.",
|
||||
"ActiveUserField": {
|
||||
"label": "Usuario activo",
|
||||
"placeholder": "Selecciona un participante...",
|
||||
"none": "Ninguno",
|
||||
"description": "Usuario que paga los gastos por defecto."
|
||||
},
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando",
|
||||
"create": "Crear",
|
||||
"creating": "Creando",
|
||||
"cancel": "Cancelar"
|
||||
}
|
||||
},
|
||||
"ExpenseForm": {
|
||||
"Income": {
|
||||
"create": "Crear ingreso",
|
||||
"edit": "Editar ingreso",
|
||||
"TitleField": {
|
||||
"label": "Título del ingreso",
|
||||
"placeholder": "Comida Hamburgeseria",
|
||||
"description": "Introduce una descripción para este ingreso."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Fecha del ingreso",
|
||||
"description": "Ingresa la fecha en que se recibio el ingreso."
|
||||
},
|
||||
"categoryFieldDescription": "Seleccione la categoría de ingresos.",
|
||||
"paidByField": {
|
||||
"label": "Recibido por",
|
||||
"description": "Seleccione el participante que recibió los ingresos."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Recibido para for",
|
||||
"description": "Seleccione para quién se recibió el ingreso."
|
||||
},
|
||||
"splitModeDescription": "Seleccione como quieres dividir el ingreso.",
|
||||
"attachDescription": "Ver y adjuntar tickets para el ingreso."
|
||||
},
|
||||
"Expense": {
|
||||
"create": "Crear gasto",
|
||||
"edit": "Editar gasto",
|
||||
"TitleField": {
|
||||
"label": "Título del gasto",
|
||||
"placeholder": "Monday evening restaurant",
|
||||
"description": "Enter a description for the expense."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Fecha del gasto",
|
||||
"description": "Ingresa la fecha en que se recibio el gasto."
|
||||
},
|
||||
"categoryFieldDescription": "Select the expense category.",
|
||||
"paidByField": {
|
||||
"label": "Pagado por",
|
||||
"description": "Seleccione el participante que pagó el gasto."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Pagado para",
|
||||
"description": "Seleccione para quién se pagó el gasto."
|
||||
},
|
||||
"splitModeDescription": "Seleccione como quieres dividir el gasto.",
|
||||
"attachDescription": "Ver y adjuntar tickets para el gasto."
|
||||
},
|
||||
"amountField": {
|
||||
"label": "Cantidad"
|
||||
},
|
||||
"isReimbursementField": {
|
||||
"label": "Esto es un reembolso"
|
||||
},
|
||||
"categoryField": {
|
||||
"label": "Categoria"
|
||||
},
|
||||
"notesField": {
|
||||
"label": "Notas"
|
||||
},
|
||||
"selectNone": "Seleccionar ninguno",
|
||||
"selectAll": "Seleccionar todos",
|
||||
"shares": "partes",
|
||||
"advancedOptions": "Opciones avanzadas",
|
||||
"SplitModeField": {
|
||||
"label": "Modo de división",
|
||||
"evenly": "Uniformemente",
|
||||
"byShares": "Desigualmente – Por partes",
|
||||
"byPercentage": "Desigualmente – por porcentaje",
|
||||
"byAmount": "Desigualmente – por cantidad",
|
||||
"saveAsDefault": "Guardar como modo preferido"
|
||||
},
|
||||
"DeletePopup": {
|
||||
"label": "Borrar",
|
||||
"title": "Borrar gasto?",
|
||||
"description": "Seguro que quieres borrar este gasto? Esta acción es irreversible.",
|
||||
"yes": "Si",
|
||||
"cancel": "Cancelar"
|
||||
},
|
||||
"attachDocuments": "Adjuntar documentos",
|
||||
"create": "Crear",
|
||||
"creating": "Creando",
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando",
|
||||
"cancel": "Cancelar"
|
||||
},
|
||||
"ExpenseDocumentsInput": {
|
||||
"TooBigToast": {
|
||||
"title": "El archivo es demasiado grande",
|
||||
"description": "El tamaño máximo de archivo que puede cargar es {maxSize}. El tuyo pesa ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Error al cargar el documento",
|
||||
"description": "Ha ocurrido un error al cargar el documento. Vuelva a intentarlo más tarde o seleccione otro archivo.",
|
||||
"retry": "Reintentar"
|
||||
}
|
||||
},
|
||||
"CreateFromReceipt": {
|
||||
"Dialog": {
|
||||
"triggerTitle": "Crear gasto desde ticket",
|
||||
"title": "Crear desde ticket",
|
||||
"description": "Extraer la información de gastos de una foto de recibo.",
|
||||
"body": "Sube la foto de un recibo y lo escanearemos para extraer la información del gasto si podemos.",
|
||||
"selectImage": "Seleccionar imagen…",
|
||||
"titleLabel": "Titulo:",
|
||||
"categoryLabel": "Categoria:",
|
||||
"amountLabel": "Cantidad:",
|
||||
"dateLabel": "Fecha:",
|
||||
"editNext": "A continuación podrá editar la información de los gastos.",
|
||||
"continue": "Continuar"
|
||||
},
|
||||
"unknown": "Desconocido",
|
||||
"TooBigToast": {
|
||||
"title": "El archivo es demasiado grande",
|
||||
"description": "El tamaño máximo de archivo que puede cargar es {maxSize}. El tuyo pesa ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Error al cargar el documento",
|
||||
"description": "Ha ocurrido un error al cargar el documento. Vuelva a intentarlo más tarde o seleccione otro archivo.",
|
||||
"retry": "Reintentar"
|
||||
}
|
||||
},
|
||||
"Balances": {
|
||||
"title": "Balances",
|
||||
"description": "Se trata del importe que ha pagado o ha recibido cada participante.",
|
||||
"Reimbursements": {
|
||||
"title": "Reembolsos propuestos",
|
||||
"description": "He aquí algunas sugerencias para optimizar los reembolsos entre los participantes.",
|
||||
"noImbursements": "Parece que tu grupo no necesita ningún reembolso 😁",
|
||||
"owes": "<strong>{from}</strong> debe <strong>{to}</strong>",
|
||||
"markAsPaid": "Marcar como pagado"
|
||||
}
|
||||
},
|
||||
"Stats": {
|
||||
"title": "Estadísticas",
|
||||
"Totals": {
|
||||
"title": "Totales",
|
||||
"description": "Resumen de gastos de todo el grupo.",
|
||||
"groupSpendings": "Gastos de todo el grupo",
|
||||
"groupEarnings": "Ingresos de todo el grupo",
|
||||
"yourSpendings": "Tus gastos totales",
|
||||
"yourEarnings": "Tus ingresos totales",
|
||||
"yourShare": "Tu parte final"
|
||||
}
|
||||
},
|
||||
"Activity": {
|
||||
"title": "Actividad",
|
||||
"description": "Aquí encontrarás todas las actividades recientes en tu grupo.",
|
||||
"noActivity": "No hay actividad reciente en este grupo.",
|
||||
"someone": "Alguien",
|
||||
"settingsModified": "Los ajustes del grupo fueron modificados por <strong>{participant}</strong>.",
|
||||
"expenseCreated": "Gasto <em>{expense}</em> creado por <strong>{participant}</strong>.",
|
||||
"expenseUpdated": "Gasto <em>{expense}</em> actualizado por <strong>{participant}</strong>.",
|
||||
"expenseDeleted": "Gasto <em>{expense}</em> borrado por <strong>{participant}</strong>.",
|
||||
"Groups": {
|
||||
"today": "Hoy",
|
||||
"yesterday": "Ayer",
|
||||
"earlierThisWeek": "A principios de esta semana",
|
||||
"lastWeek": "La semana pasada",
|
||||
"earlierThisMonth": "A principios de este mes",
|
||||
"lastMonth": "El mes pasado",
|
||||
"earlierThisYear": "A principios de este año",
|
||||
"lastYear": "El ultimo año",
|
||||
"older": "Más antiguos"
|
||||
}
|
||||
},
|
||||
"Information": {
|
||||
"title": "Información",
|
||||
"description": "Utilice este lugar para añadir cualquier información que pueda ser relevante para los participantes del grupo.",
|
||||
"empty": "Aún no hay información sobre el grupo."
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Ajustes"
|
||||
},
|
||||
"Locale": {
|
||||
"en-US": "English",
|
||||
"fi": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"es": "Español",
|
||||
"de-DE": "Deutsch",
|
||||
"zh-CN": "Chinese (Simplified)",
|
||||
"ru-RU": "Русский"
|
||||
},
|
||||
"Share": {
|
||||
"title": "Compartir",
|
||||
"description": "Para que otros participantes puedan ver el grupo y añadir gastos, compárteles su URL.",
|
||||
"warning": "Cuidado!",
|
||||
"warningHelp": "Todas las personas que tengan la URL del grupo podrán ver y editar los gastos. ¡Comparte con precaución!"
|
||||
},
|
||||
"SchemaErrors": {
|
||||
"min1": "Introduzca al menos un carácter.",
|
||||
"min2": "Introduzca al menos dos carácter.",
|
||||
"max5": "Introduzca al menos cinco carácter.",
|
||||
"max50": "Introduzca al menos treinta carácter.",
|
||||
"duplicateParticipantName": "Otro participante ya tiene este nombre",
|
||||
"titleRequired": "Por favor, introduzca un título",
|
||||
"invalidNumber": "Número inválido",
|
||||
"amountRequired": "Debe introducir un importe",
|
||||
"amountNotZero": "El importe no debe ser cero.",
|
||||
"amountTenMillion": "El importe debe ser inferior a 10.000.000.",
|
||||
"paidByRequired": "Debe seleccionar un participante",
|
||||
"paidForMin1": "El gasto debe ser pagado por al menos un participante",
|
||||
"noZeroShares": "Todas las participaciones deben ser superiores a 0",
|
||||
"amountSum": "La suma de los importes debe ser igual al importe del gasto",
|
||||
"percentageSum": "Suma de porcentajes debe ser igual a 100"
|
||||
},
|
||||
"Categories": {
|
||||
"search": "Buscar categoría...",
|
||||
"noCategory": "Categoría no encontrada!",
|
||||
"Uncategorized": {
|
||||
"heading": "Sin categoría",
|
||||
"General": "General",
|
||||
"Payment": "Pago"
|
||||
},
|
||||
"Entertainment": {
|
||||
"heading": "Ocio",
|
||||
"Entertainment": "Ocio",
|
||||
"Games": "Juegos",
|
||||
"Movies": "Películas",
|
||||
"Music": "Musica",
|
||||
"Sports": "Deportes"
|
||||
},
|
||||
"Food and Drink": {
|
||||
"heading": "Comida y bebida",
|
||||
"Food and Drink": "Comida y bebida",
|
||||
"Dining Out": "Comer fuera",
|
||||
"Groceries": "Comestibles",
|
||||
"Liquor": "Licores"
|
||||
},
|
||||
"Home": {
|
||||
"heading": "Hogar",
|
||||
"Home": "Hogar",
|
||||
"Electronics": "Electrónica",
|
||||
"Furniture": "Muebles",
|
||||
"Household Supplies": "Suministros del hogar",
|
||||
"Maintenance": "Mantenimiento",
|
||||
"Mortgage": "Hipoteca",
|
||||
"Pets": "Mascotas",
|
||||
"Rent": "Alquiler",
|
||||
"Services": "Servicios"
|
||||
},
|
||||
"Life": {
|
||||
"heading": "Vida",
|
||||
"Childcare": "Cuidado de niños",
|
||||
"Clothing": "Ropa",
|
||||
"Education": "Educación",
|
||||
"Gifts": "Regalos",
|
||||
"Insurance": "Seguro",
|
||||
"Medical Expenses": "Gastos médicos",
|
||||
"Taxes": "Impuestos"
|
||||
},
|
||||
"Transportation": {
|
||||
"heading": "Transporte",
|
||||
"Transportation": "Transporte",
|
||||
"Bicycle": "Bicicleta",
|
||||
"Bus/Train": "Autobús/Tren",
|
||||
"Car": "Coche",
|
||||
"Gas/Fuel": "Gasolina/Combustible",
|
||||
"Hotel": "Hotel",
|
||||
"Parking": "Parking",
|
||||
"Plane": "Avión",
|
||||
"Taxi": "Taxi"
|
||||
},
|
||||
"Utilities": {
|
||||
"heading": "Utilidades",
|
||||
"Utilities": "Utilidades",
|
||||
"Cleaning": "Limpieza",
|
||||
"Electricity": "Electricidad",
|
||||
"Heat/Gas": "Calefacción/Gas",
|
||||
"Trash": "Basura",
|
||||
"TV/Phone/Internet": "TV/Teléfono/Internet",
|
||||
"Water": "Agua"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
{
|
||||
"Homepage": {
|
||||
"title": "Jaa kulut ystävien ja perheen kanssa",
|
||||
"description": "Tervetuloa uuteen Spliit-instanssiisi!",
|
||||
"button": {
|
||||
"groups": "Siirry ryhmiin",
|
||||
"github": "GitHub"
|
||||
}
|
||||
},
|
||||
"Header": {
|
||||
"groups": "Ryhmät"
|
||||
},
|
||||
@@ -287,7 +295,12 @@
|
||||
},
|
||||
"Locale": {
|
||||
"en-US": "English",
|
||||
"fi": "Suomi"
|
||||
"fi": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"es": "Español",
|
||||
"de-DE": "Deutsch",
|
||||
"zh-CN": "Chinese (Simplified)",
|
||||
"ru-RU": "Русский"
|
||||
},
|
||||
"Share": {
|
||||
"title": "Jaa",
|
||||
|
||||
396
messages/fr-FR.json
Normal file
396
messages/fr-FR.json
Normal file
@@ -0,0 +1,396 @@
|
||||
{
|
||||
"Homepage": {
|
||||
"title": "Partagez <strong>vos dépenses</strong> avec <strong>vos amis</strong> & <strong>votre famille :)</strong>",
|
||||
"description": "Bienvenue sur votre instance <strong>Spliit</strong> !",
|
||||
"button": {
|
||||
"groups": "Accéder aux groupes",
|
||||
"github": "GitHub"
|
||||
}
|
||||
},
|
||||
"Header": {
|
||||
"groups": "Groupes"
|
||||
},
|
||||
"Footer": {
|
||||
"madeIn": "Made in Montréal, Québec 🇨🇦",
|
||||
"builtBy": "Développé par <author>Sebastien Castiel</author> et <source>contributeurs</source>"
|
||||
},
|
||||
"Expenses": {
|
||||
"title": "Dépenses",
|
||||
"description": "Voici les dépenses que vous avez créées pour votre groupe.",
|
||||
"create": "Créer une dépense",
|
||||
"createFirst": "Créer la première :)",
|
||||
"noExpenses": "Votre groupe n'a effectué aucune dépense pour le moment.",
|
||||
"exportJson": "Exporter en JSON",
|
||||
"searchPlaceholder": "Rechercher une dépense…",
|
||||
"ActiveUserModal": {
|
||||
"title": "Qui êtes-vous ?",
|
||||
"description": "Dites-nous quel participant vous êtes pour personnaliser l'affichage des informations.",
|
||||
"nobody": "Je ne veux sélectionner personne",
|
||||
"save": "Sauvegarder les modifications",
|
||||
"footer": "Ce paramètre peut être modifié plus tard dans les paramètres du groupe."
|
||||
},
|
||||
"Groups": {
|
||||
"upcoming": "À venir",
|
||||
"thisWeek": "Cette semaine",
|
||||
"earlierThisMonth": "Plus tôt ce mois-ci",
|
||||
"lastMonth": "Le mois dernier",
|
||||
"earlierThisYear": "Plus tôt cette année",
|
||||
"lastYera": "L'année dernière",
|
||||
"older": "Plus ancien"
|
||||
}
|
||||
},
|
||||
"ExpenseCard": {
|
||||
"paidBy": "Payé par <strong>{paidBy}</strong> pour <paidFor></paidFor>",
|
||||
"receivedBy": "Reçu par <strong>{paidBy}</strong> pour <paidFor></paidFor>",
|
||||
"yourBalance": "Votre solde :"
|
||||
},
|
||||
"Groups": {
|
||||
"myGroups": "Mes groupes",
|
||||
"create": "Créer",
|
||||
"loadingRecent": "Chargement des groupes récents…",
|
||||
"NoRecent": {
|
||||
"description": "Vous n'avez visité aucun groupe récemment.",
|
||||
"create": "Créer un groupe",
|
||||
"orAsk": "ou demandez à un ami de vous envoyer le lien d'un groupe existant."
|
||||
},
|
||||
"recent": "Groupes récents",
|
||||
"starred": "Groupes favoris",
|
||||
"archived": "Groupes archivés",
|
||||
"archive": "Archiver le groupe",
|
||||
"unarchive": "Désarchiver le groupe",
|
||||
"removeRecent": "Supprimer des groupes récents",
|
||||
"RecentRemovedToast": {
|
||||
"title": "Le groupe a été supprimé",
|
||||
"description": "Le groupe a été supprimé de votre liste de groupes récents.",
|
||||
"undoAlt": "Annuler la suppression du groupe",
|
||||
"undo": "Annuler"
|
||||
},
|
||||
"AddByURL": {
|
||||
"button": "Ajouter par URL",
|
||||
"title": "Ajouter un groupe par URL",
|
||||
"description": "Si un groupe a été partagé avec vous, vous pouvez coller son URL ici pour l'ajouter à votre liste.",
|
||||
"error": "Oups, nous ne pouvons pas trouver le groupe à partir de l'URL que vous avez fournie…"
|
||||
},
|
||||
"NotFound": {
|
||||
"text": "Ce groupe n'existe pas.",
|
||||
"link": "Aller aux groupes récemment visités"
|
||||
}
|
||||
},
|
||||
"GroupForm": {
|
||||
"title": "Informations sur le groupe",
|
||||
"NameField": {
|
||||
"label": "Nom du groupe",
|
||||
"placeholder": "Vacances d'été",
|
||||
"description": "Entrez un nom pour votre groupe."
|
||||
},
|
||||
"InformationField": {
|
||||
"label": "Informations sur le groupe",
|
||||
"placeholder": "Quelles informations sont pertinentes pour les participants du groupe ?"
|
||||
},
|
||||
"CurrencyField": {
|
||||
"label": "Symbole monétaire",
|
||||
"placeholder": "$, €, £…",
|
||||
"description": "Nous l'utiliserons pour afficher les montants."
|
||||
},
|
||||
"Participants": {
|
||||
"title": "Participants",
|
||||
"description": "Entrez le nom de chaque participant.",
|
||||
"protectedParticipant": "Ce participant fait partie des dépenses et ne peut pas être supprimé.",
|
||||
"new": "Nouveau",
|
||||
"add": "Ajouter un participant",
|
||||
"John": "John",
|
||||
"Jane": "Jane",
|
||||
"Jack": "Jack"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Paramètres locaux",
|
||||
"description": "Ces paramètres sont définis par appareil et sont utilisés pour personnaliser votre expérience.",
|
||||
"ActiveUserField": {
|
||||
"label": "Utilisateur actif",
|
||||
"placeholder": "Sélectionner un participant",
|
||||
"none": "Aucun",
|
||||
"description": "Utilisateur utilisé comme défaut pour payer les dépenses."
|
||||
},
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde…",
|
||||
"create": "Créer",
|
||||
"creating": "Création…",
|
||||
"cancel": "Annuler"
|
||||
}
|
||||
},
|
||||
"ExpenseForm": {
|
||||
"Income": {
|
||||
"create": "Créer un revenu",
|
||||
"edit": "Modifier le revenu",
|
||||
"TitleField": {
|
||||
"label": "Titre du revenu",
|
||||
"placeholder": "Restaurant du lundi soir",
|
||||
"description": "Entrez une description pour le revenu."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Date du revenu",
|
||||
"description": "Entrez la date à laquelle le revenu a été reçu."
|
||||
},
|
||||
"categoryFieldDescription": "Sélectionnez la catégorie de revenu.",
|
||||
"paidByField": {
|
||||
"label": "Reçu par",
|
||||
"description": "Sélectionnez le participant qui a reçu le revenu."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Reçu pour",
|
||||
"description": "Sélectionnez pour qui le revenu a été reçu."
|
||||
},
|
||||
"splitModeDescription": "Sélectionnez comment diviser le revenu.",
|
||||
"attachDescription": "Voir et joindre des reçus au revenu."
|
||||
},
|
||||
"Expense": {
|
||||
"create": "Créer une dépense",
|
||||
"edit": "Modifier la dépense",
|
||||
"TitleField": {
|
||||
"label": "Titre de la dépense",
|
||||
"placeholder": "Restaurant du lundi soir",
|
||||
"description": "Entrez une description pour la dépense."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Date de la dépense",
|
||||
"description": "Entrez la date à laquelle la dépense a été payée."
|
||||
},
|
||||
"categoryFieldDescription": "Sélectionnez la catégorie de dépense.",
|
||||
"paidByField": {
|
||||
"label": "Payé par",
|
||||
"description": "Sélectionnez le participant qui a réglé la dépense."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Payé pour",
|
||||
"description": "Sélectionnez les participants concernés"
|
||||
},
|
||||
"splitModeDescription": "Sélectionnez comment diviser la dépense.",
|
||||
"attachDescription": "Voir et joindre des reçus à la dépense."
|
||||
},
|
||||
"amountField": {
|
||||
"label": "Montant"
|
||||
},
|
||||
"isReimbursementField": {
|
||||
"label": "C'est un remboursement"
|
||||
},
|
||||
"categoryField": {
|
||||
"label": "Catégorie"
|
||||
},
|
||||
"notesField": {
|
||||
"label": "Notes"
|
||||
},
|
||||
"selectNone": "Tout désélectionner",
|
||||
"selectAll": "Tout sélectionner",
|
||||
"shares": "part(s)",
|
||||
"advancedOptions": "Options de répartition avancées…",
|
||||
"SplitModeField": {
|
||||
"label": "Mode de répartition",
|
||||
"evenly": "Également",
|
||||
"byShares": "Inégalement – Par parts",
|
||||
"byPercentage": "Inégalement – Par pourcentage",
|
||||
"byAmount": "Inégalement – Par montant",
|
||||
"saveAsDefault": "Enregistrer comme options de répartition par défaut"
|
||||
},
|
||||
"DeletePopup": {
|
||||
"label": "Supprimer",
|
||||
"title": "Supprimer cette dépense ?",
|
||||
"description": "Voulez-vous vraiment supprimer cette dépense ? Cette action est irréversible.",
|
||||
"yes": "Oui",
|
||||
"cancel": "Annuler"
|
||||
},
|
||||
"attachDocuments": "Joindre des documents",
|
||||
"create": "Créer",
|
||||
"creating": "Création…",
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde…",
|
||||
"cancel": "Annuler"
|
||||
},
|
||||
"ExpenseDocumentsInput": {
|
||||
"TooBigToast": {
|
||||
"title": "Le fichier est trop grand",
|
||||
"description": "La taille maximale du fichier que vous pouvez télécharger est {maxSize}. La vôtre est ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Erreur lors du téléchargement du document",
|
||||
"description": "Un problème est survenu lors du téléchargement du document. Veuillez réessayer plus tard ou sélectionner un fichier différent.",
|
||||
"retry": "Réessayer"
|
||||
}
|
||||
},
|
||||
"CreateFromReceipt": {
|
||||
"Dialog": {
|
||||
"triggerTitle": "Créer une dépense à partir du reçu",
|
||||
"title": "Créer à partir du reçu",
|
||||
"description": "Extraire les informations de la dépense à partir d'une photo de reçu.",
|
||||
"body": "Téléchargez la photo d'un reçu, et nous l'analyserons pour extraire les informations de la dépense si possible.",
|
||||
"selectImage": "Sélectionner une image…",
|
||||
"titleLabel": "Titre :",
|
||||
"categoryLabel": "Catégorie :",
|
||||
"amountLabel": "Montant :",
|
||||
"dateLabel": "Date :",
|
||||
"editNext": "Vous pourrez modifier les informations de la dépense ensuite.",
|
||||
"continue": "Continuer"
|
||||
},
|
||||
"unknown": "Inconnu",
|
||||
"TooBigToast": {
|
||||
"title": "Le fichier est trop grand",
|
||||
"description": "La taille maximale du fichier que vous pouvez télécharger est {maxSize}. La vôtre est ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Erreur lors du téléchargement du document",
|
||||
"description": "Un problème est survenu lors du téléchargement du document. Veuillez réessayer plus tard ou sélectionner un fichier différent.",
|
||||
"retry": "Réessayer"
|
||||
}
|
||||
},
|
||||
"Balances": {
|
||||
"title": "Équilibres",
|
||||
"description": "Voici le montant que chaque participant a payé ou doit rembourser.",
|
||||
"Reimbursements": {
|
||||
"title": "Remboursements suggérés",
|
||||
"description": "Voici des suggestions pour des remboursements optimisés entre les participants.",
|
||||
"noImbursements": "Les dépenses effectuées ne nécessitent pas d'équilibrage 😁",
|
||||
"owes": "<strong>{from}</strong> doit à <strong>{to}</strong>",
|
||||
"markAsPaid": "Marquer comme payé"
|
||||
}
|
||||
},
|
||||
"Stats": {
|
||||
"title": "Statistiques",
|
||||
"Totals": {
|
||||
"title": "Totaux",
|
||||
"description": "Résumé des dépenses du groupe entier.",
|
||||
"groupSpendings": "Total des dépenses du groupe",
|
||||
"groupEarnings": "Total des revenus du groupe",
|
||||
"yourSpendings": "Vos dépenses totales",
|
||||
"yourEarnings": "Vos revenus totaux",
|
||||
"yourShare": "Votre part totale"
|
||||
}
|
||||
},
|
||||
"Activity": {
|
||||
"title": "Activité",
|
||||
"description": "Vue d'ensemble de toute l'activité dans ce groupe.",
|
||||
"noActivity": "Il n'y a pas encore d'activité dans votre groupe.",
|
||||
"someone": "Quelqu'un",
|
||||
"settingsModified": "Les paramètres du groupe ont été modifiés par <strong>{participant}</strong>.",
|
||||
"expenseCreated": "Dépense <em>{expense}</em> créée par <strong>{participant}</strong>.",
|
||||
"expenseUpdated": "Dépense <em>{expense}</em> mise à jour par <strong>{participant}</strong>.",
|
||||
"expenseDeleted": "Dépense <em>{expense}</em> supprimée par <strong>{participant}</strong>.",
|
||||
"Groups": {
|
||||
"today": "Aujourd'hui",
|
||||
"yesterday": "Hier",
|
||||
"earlierThisWeek": "Plus tôt cette semaine",
|
||||
"lastWeek": "La semaine dernière",
|
||||
"earlierThisMonth": "Plus tôt ce mois-ci",
|
||||
"lastMonth": "Le mois dernier",
|
||||
"earlierThisYear": "Plus tôt cette année",
|
||||
"lastYear": "L'année dernière",
|
||||
"older": "Plus ancien"
|
||||
}
|
||||
},
|
||||
"Information": {
|
||||
"title": "Information",
|
||||
"description": "Utilisez cet espace pour ajouter toute information qui pourrait être pertinente pour les participants du groupe.",
|
||||
"empty": "Aucune information pour le moment."
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Paramètres"
|
||||
},
|
||||
"Locale": {
|
||||
"en-US": "English",
|
||||
"fi": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"es": "Español",
|
||||
"de-DE": "Deutsch",
|
||||
"zh-CN": "Chinese (Simplified)",
|
||||
"ru-RU": "Русский"
|
||||
},
|
||||
"Share": {
|
||||
"title": "Partager",
|
||||
"description": "Pour que d'autres participants puissent voir le groupe et ajouter des dépenses, partagez son URL avec eux.",
|
||||
"warning": "Avertissement !",
|
||||
"warningHelp": "Toute personne ayant l'URL du groupe pourra voir et modifier les dépenses. Partagez avec prudence !"
|
||||
},
|
||||
"SchemaErrors": {
|
||||
"min1": "Entrez au moins un caractère.",
|
||||
"min2": "Entrez au moins deux caractères.",
|
||||
"max5": "Entrez au maximum cinq caractères.",
|
||||
"max50": "Entrez au maximum 50 caractères.",
|
||||
"duplicateParticipantName": "Un autre participant a déjà ce nom.",
|
||||
"titleRequired": "Veuillez entrer un titre.",
|
||||
"invalidNumber": "Nombre invalide.",
|
||||
"amountRequired": "Vous devez entrer un montant.",
|
||||
"amountNotZero": "Le montant ne doit pas être zéro.",
|
||||
"amountTenMillion": "Le montant doit être inférieur à 10 000 000.",
|
||||
"paidByRequired": "Vous devez sélectionner un participant.",
|
||||
"paidForMin1": "La dépense doit concerner au moins un participant.",
|
||||
"noZeroShares": "Toutes les parts doivent être supérieures à 0.",
|
||||
"amountSum": "La somme des montants doit être égale au montant de la dépense.",
|
||||
"percentageSum": "La somme des pourcentages doit être égale à 100."
|
||||
},
|
||||
"Categories": {
|
||||
"search": "Rechercher une catégorie…",
|
||||
"noCategory": "Aucune catégorie trouvée.",
|
||||
"Uncategorized": {
|
||||
"heading": "Non classé",
|
||||
"General": "Général",
|
||||
"Payment": "Paiement"
|
||||
},
|
||||
"Entertainment": {
|
||||
"heading": "Divertissement",
|
||||
"Entertainment": "Divertissement",
|
||||
"Games": "Jeux",
|
||||
"Movies": "Films",
|
||||
"Music": "Musique",
|
||||
"Sports": "Sports"
|
||||
},
|
||||
"Food and Drink": {
|
||||
"heading": "Nourriture et boissons",
|
||||
"Food and Drink": "Nourriture et boissons",
|
||||
"Dining Out": "Repas au restaurant",
|
||||
"Groceries": "Épicerie",
|
||||
"Liquor": "Alcool"
|
||||
},
|
||||
"Home": {
|
||||
"heading": "Maison",
|
||||
"Home": "Maison",
|
||||
"Electronics": "Électronique",
|
||||
"Furniture": "Mobilier",
|
||||
"Household Supplies": "Fournitures ménagères",
|
||||
"Maintenance": "Entretien",
|
||||
"Mortgage": "Hypothèque",
|
||||
"Pets": "Animaux",
|
||||
"Rent": "Loyer",
|
||||
"Services": "Services"
|
||||
},
|
||||
"Life": {
|
||||
"heading": "Vie",
|
||||
"Childcare": "Garde d'enfants",
|
||||
"Clothing": "Vêtements",
|
||||
"Education": "Éducation",
|
||||
"Gifts": "Cadeaux",
|
||||
"Insurance": "Assurance",
|
||||
"Medical Expenses": "Dépenses médicales",
|
||||
"Taxes": "Impôts"
|
||||
},
|
||||
"Transportation": {
|
||||
"heading": "Transport",
|
||||
"Transportation": "Transport",
|
||||
"Bicycle": "Bicyclette",
|
||||
"Bus/Train": "Bus/Train",
|
||||
"Car": "Voiture",
|
||||
"Gas/Fuel": "Essence/Carburant",
|
||||
"Hotel": "Hôtel",
|
||||
"Parking": "Parking",
|
||||
"Plane": "Avion",
|
||||
"Taxi": "Taxi"
|
||||
},
|
||||
"Utilities": {
|
||||
"heading": "Services publics",
|
||||
"Utilities": "Services publics",
|
||||
"Cleaning": "Nettoyage",
|
||||
"Electricity": "Électricité",
|
||||
"Heat/Gas": "Chauffage/Gaz",
|
||||
"Trash": "Poubelle",
|
||||
"TV/Phone/Internet": "TV/Téléphone/Internet",
|
||||
"Water": "Eau"
|
||||
}
|
||||
}
|
||||
}
|
||||
396
messages/ru-RU.json
Normal file
396
messages/ru-RU.json
Normal file
@@ -0,0 +1,396 @@
|
||||
{
|
||||
"Homepage": {
|
||||
"title": "Делитесь <strong>расходами</strong> с <strong>друзьями и семьей</strong>",
|
||||
"description": "Добро пожаловать в вашу новую инстанцию <strong>Spliit</strong>!",
|
||||
"button": {
|
||||
"groups": "Перейти к группам",
|
||||
"github": "GitHub"
|
||||
}
|
||||
},
|
||||
"Header": {
|
||||
"groups": "Группы"
|
||||
},
|
||||
"Footer": {
|
||||
"madeIn": "Сделано в Монреале, Квебек 🇨🇦",
|
||||
"builtBy": "Создано <author>Sebastien Castiel</author> и <source>соавторами</source>"
|
||||
},
|
||||
"Expenses": {
|
||||
"title": "Расходы",
|
||||
"description": "В этом разделе находятся расходы вашей группы.",
|
||||
"create": "Создать расход",
|
||||
"createFirst": "Создать первый расход",
|
||||
"noExpenses": "У вашей группы пока что нет расходов.",
|
||||
"exportJson": "Экспортировать в JSON",
|
||||
"searchPlaceholder": "Поиск расходов…",
|
||||
"ActiveUserModal": {
|
||||
"title": "Кто вы?",
|
||||
"description": "Скажите нам, кто вы из этого списка, чтобы мы могли подстроить интерфейс под вас.",
|
||||
"nobody": "Не хочу выбирать",
|
||||
"save": "Сохранить изменения",
|
||||
"footer": "Вы сможете изменить это в настройках группы."
|
||||
},
|
||||
"Groups": {
|
||||
"upcoming": "Будущее",
|
||||
"thisWeek": "На этой неделе",
|
||||
"earlierThisMonth": "Ранее в этом месяце",
|
||||
"lastMonth": "В прошлом месяце",
|
||||
"earlierThisYear": "Ранее в этом году",
|
||||
"lastYera": "В прошлом году",
|
||||
"older": "Очень давно"
|
||||
}
|
||||
},
|
||||
"ExpenseCard": {
|
||||
"paidBy": "Потратил <strong>{paidBy}</strong> за <paidFor></paidFor>",
|
||||
"receivedBy": "Получил <strong>{paidBy}</strong> за <paidFor></paidFor>",
|
||||
"yourBalance": "Изменение баланса участника:"
|
||||
},
|
||||
"Groups": {
|
||||
"myGroups": "Мои группы",
|
||||
"create": "Создать",
|
||||
"loadingRecent": "Загрузка недавних групп…",
|
||||
"NoRecent": {
|
||||
"description": "У вас нет недавних групп.",
|
||||
"create": "Вы можете создать группу",
|
||||
"orAsk": "или попросить вашего друга отправить вам ссылку на существующую."
|
||||
},
|
||||
"recent": "Недавние группы",
|
||||
"starred": "Избранные",
|
||||
"archived": "Архивированные группы",
|
||||
"archive": "Архивировать группу",
|
||||
"unarchive": "Восстановить группу",
|
||||
"removeRecent": "Убрать группу из недавних",
|
||||
"RecentRemovedToast": {
|
||||
"title": "Группа убрана",
|
||||
"description": "Группа была убрана из вашего списка недавних групп.",
|
||||
"undoAlt": "Отменить удаление группы из этого списка",
|
||||
"undo": "Отмена"
|
||||
},
|
||||
"AddByURL": {
|
||||
"button": "Добавить по URL",
|
||||
"title": "Добавить группу по URL",
|
||||
"description": "Если с вами поделились ссылкой на группу, вставьте ее сюда, чтобы добавить ее в ваш список.",
|
||||
"error": "К сожалению, мы не смогли найти группу по этому URL."
|
||||
},
|
||||
"NotFound": {
|
||||
"text": "Этой группы не существует",
|
||||
"link": "Перейти к списку недавних групп"
|
||||
}
|
||||
},
|
||||
"GroupForm": {
|
||||
"title": "Сведения о группе",
|
||||
"NameField": {
|
||||
"label": "Название группы",
|
||||
"placeholder": "Летние поездки",
|
||||
"description": "Введите название вашей группы."
|
||||
},
|
||||
"InformationField": {
|
||||
"label": "Информация о группе",
|
||||
"placeholder": "Что важно знать участникам этой группы?"
|
||||
},
|
||||
"CurrencyField": {
|
||||
"label": "Символ валюты",
|
||||
"placeholder": "$, €, £…",
|
||||
"description": "Этот символ будет использован для отображений денежных сумм."
|
||||
},
|
||||
"Participants": {
|
||||
"title": "Участники",
|
||||
"description": "Введите имя каждого участника.",
|
||||
"protectedParticipant": "Этот участник — часть расходов, и поэтому не может быть удален.",
|
||||
"new": "Новый участник",
|
||||
"add": "Добавить участника",
|
||||
"John": "Александр",
|
||||
"Jane": "Михаил",
|
||||
"Jack": "Иван"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Локальные настройки",
|
||||
"description": "Эти настройки хранятся на вашем устройстве и используются для подстройки интерфейса для вас.",
|
||||
"ActiveUserField": {
|
||||
"label": "Активный участник",
|
||||
"placeholder": "Выберите участника",
|
||||
"none": "Не выбран",
|
||||
"description": "Этот участник будет автоматически выбран при создании нового расхода."
|
||||
},
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение…",
|
||||
"create": "Создать",
|
||||
"creating": "Создание…",
|
||||
"cancel": "Отмена"
|
||||
}
|
||||
},
|
||||
"ExpenseForm": {
|
||||
"Income": {
|
||||
"create": "Создать доход",
|
||||
"edit": "Изменить доход",
|
||||
"TitleField": {
|
||||
"label": "Название доходв",
|
||||
"placeholder": "Поход в ресторан",
|
||||
"description": "Введите описание для этого дохода."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Дата дохода",
|
||||
"description": "Введите дату, когда этот доход был получен."
|
||||
},
|
||||
"categoryFieldDescription": "Выберите категорию дохода.",
|
||||
"paidByField": {
|
||||
"label": "Получивший",
|
||||
"description": "Выберите участника, который получил этот доход."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Участники",
|
||||
"description": "Выберите тех, между кем этот доход будет распределен."
|
||||
},
|
||||
"splitModeDescription": "Выберите, как доход необходимо распределить между людьми.",
|
||||
"attachDescription": "Просмотр и прикрепление чеков к этому расходу."
|
||||
},
|
||||
"Expense": {
|
||||
"create": "Создать расход",
|
||||
"edit": "Изменить расход",
|
||||
"TitleField": {
|
||||
"label": "Название расхода",
|
||||
"placeholder": "Поход в ресторан",
|
||||
"description": "Введите описание для этого расхода."
|
||||
},
|
||||
"DateField": {
|
||||
"label": "Дата расхода",
|
||||
"description": "Введите дату, когда этот расход был совершен."
|
||||
},
|
||||
"categoryFieldDescription": "Выберите категорию расхода.",
|
||||
"paidByField": {
|
||||
"label": "Оплативший",
|
||||
"description": "Выберите участника, который оплатил этот расход."
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "Участники",
|
||||
"description": "Выберите тех, между кем этот расход будет распределен. Если этот расход — возмещение участнику (участникам), выберите только его (их)."
|
||||
},
|
||||
"splitModeDescription": "Выберите, как расход необходимо распределить между людьми.",
|
||||
"attachDescription": "Просмотр и прикрепление чеков к этому доходу."
|
||||
},
|
||||
"amountField": {
|
||||
"label": "Сумма"
|
||||
},
|
||||
"isReimbursementField": {
|
||||
"label": "Этот расход является возмещением"
|
||||
},
|
||||
"categoryField": {
|
||||
"label": "Категория"
|
||||
},
|
||||
"notesField": {
|
||||
"label": "Заметки"
|
||||
},
|
||||
"selectNone": "Выбрать никого",
|
||||
"selectAll": "Выбрать всех",
|
||||
"shares": "доля(и)",
|
||||
"advancedOptions": "Дополнительные настройки распределения…",
|
||||
"SplitModeField": {
|
||||
"label": "Режим разделения",
|
||||
"evenly": "Равный",
|
||||
"byShares": "Неравный – По долям",
|
||||
"byPercentage": "Неравный – По процентам",
|
||||
"byAmount": "Неравный – По суммам",
|
||||
"saveAsDefault": "Сделать режимом по умолчанию"
|
||||
},
|
||||
"DeletePopup": {
|
||||
"label": "Удалить",
|
||||
"title": "Удалить этот расход?",
|
||||
"description": "Вы действительно хотите удалить этот расход? Это действие нельзя отменить.",
|
||||
"yes": "Удалить",
|
||||
"cancel": "Отмена"
|
||||
},
|
||||
"attachDocuments": "Прикрепить документы",
|
||||
"create": "Создать",
|
||||
"creating": "Создание…",
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение…",
|
||||
"cancel": "Отмена"
|
||||
},
|
||||
"ExpenseDocumentsInput": {
|
||||
"TooBigToast": {
|
||||
"title": "Файл слишком большой",
|
||||
"description": "Максимальный размер файла, который можно загрузить — {maxSize}. Размер вашего файла — ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Ошибка при загрузке документа",
|
||||
"description": "При загрузке документа что-то пошло не так. Пожалуйста, повторите позднее или попробуйте загрузить другой файл.",
|
||||
"retry": "Повторить"
|
||||
}
|
||||
},
|
||||
"CreateFromReceipt": {
|
||||
"Dialog": {
|
||||
"triggerTitle": "Создать расход из чека",
|
||||
"title": "Создать из чека",
|
||||
"description": "Извлечение информации о расходах из фотографии чека",
|
||||
"body": "Загрузите фотографию чека, и мы попытаемся отсканировать его, чтобы извлечь информацию о расходах.",
|
||||
"selectImage": "Выбрать изображение…",
|
||||
"titleLabel": "Название:",
|
||||
"categoryLabel": "Категория:",
|
||||
"amountLabel": "Сумма:",
|
||||
"dateLabel": "Дата:",
|
||||
"editNext": "Вы сможете изменить эту информацию позднее.",
|
||||
"continue": "Продолжить"
|
||||
},
|
||||
"unknown": "Неизвестно",
|
||||
"TooBigToast": {
|
||||
"title": "Файл слишком большой",
|
||||
"description": "Максимальный размер файла, который можно загрузить — {maxSize}. Размер вашего файла — ${size}."
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "Ошибка при загрузке документа",
|
||||
"description": "При загрузке документа что-то пошло не так. Пожалуйста, повторите позднее или попробуйте загрузить другой файл.",
|
||||
"retry": "Повторить"
|
||||
}
|
||||
},
|
||||
"Balances": {
|
||||
"title": "Балансы",
|
||||
"description": "Это список балансов всех участников группы. Баланс увеличивается у тех, кто оплачивает расход, и уменьшается у тех, между кем он был распределен.",
|
||||
"Reimbursements": {
|
||||
"title": "Предложенные возмещения",
|
||||
"description": "Вот список задолженностей между участниками.",
|
||||
"noImbursements": "Похоже, все в расчете 😁",
|
||||
"owes": "<strong>{from}</strong> должен <strong>{to}</strong>",
|
||||
"markAsPaid": "Пометить оплаченным"
|
||||
}
|
||||
},
|
||||
"Stats": {
|
||||
"title": "Статистика",
|
||||
"Totals": {
|
||||
"title": "Итоговые суммы",
|
||||
"description": "Общая информация о расходах вашей группы.",
|
||||
"groupSpendings": "Всего потрачено группой",
|
||||
"groupEarnings": "Всего заработано группой",
|
||||
"yourSpendings": "Всего потрачено вами",
|
||||
"yourEarnings": "Всего заработано вами",
|
||||
"yourShare": "Ваша суммарная доля"
|
||||
}
|
||||
},
|
||||
"Activity": {
|
||||
"title": "Активность",
|
||||
"description": "Обзор действий, совершенных участниками этой группы.",
|
||||
"noActivity": "История действий пуста.",
|
||||
"someone": "Аноним",
|
||||
"settingsModified": "Настройки группы изменены участником <strong>{participant}</strong>.",
|
||||
"expenseCreated": "Расход <em>{expense}</em> создан участником <strong>{participant}</strong>.",
|
||||
"expenseUpdated": "Расход <em>{expense}</em> изменен участником <strong>{participant}</strong>.",
|
||||
"expenseDeleted": "Расход <em>{expense}</em> удален участником <strong>{participant}</strong>.",
|
||||
"Groups": {
|
||||
"today": "Сегодня",
|
||||
"yesterday": "Вчера",
|
||||
"earlierThisWeek": "Ранее на этой неделе",
|
||||
"lastWeek": "На прошлой неделе",
|
||||
"earlierThisMonth": "Ранее в этом месяце",
|
||||
"lastMonth": "В прошлом месяце",
|
||||
"earlierThisYear": "Ранее в этом году",
|
||||
"lastYear": "В прошлом году",
|
||||
"older": "Очень давно"
|
||||
}
|
||||
},
|
||||
"Information": {
|
||||
"title": "Информация",
|
||||
"description": "В этом разделе вы можете добавить важную для участников информацию.",
|
||||
"empty": "Информации нет."
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Настройки"
|
||||
},
|
||||
"Locale": {
|
||||
"en-US": "English",
|
||||
"fi": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"es": "Español",
|
||||
"de-DE": "Deutsch",
|
||||
"zh-CN": "Chinese (Simplified)",
|
||||
"ru-RU": "Русский"
|
||||
},
|
||||
"Share": {
|
||||
"title": "Поделиться",
|
||||
"description": "Чтобы другие участники получили доступ к этой группе и смогли добавлять расходы, отправьте им этот URL.",
|
||||
"warning": "Внимание!",
|
||||
"warningHelp": "Любой человек с доступом к этой ссылке сможет просматривать и редактировать расходы. Будьте осторожны!"
|
||||
},
|
||||
"SchemaErrors": {
|
||||
"min1": "Введите как минимум один символ.",
|
||||
"min2": "Введите как минимум два символа.",
|
||||
"max5": "Введите максимум 5 символов.",
|
||||
"max50": "Введите максимум 50 символов.",
|
||||
"duplicateParticipantName": "Участник с таким именем уже существует.",
|
||||
"titleRequired": "Пожалуйста, введите название.",
|
||||
"invalidNumber": "Неверное число.",
|
||||
"amountRequired": "Пожалуйста, введите сумму.",
|
||||
"amountNotZero": "Сумма не может быть нулевой.",
|
||||
"amountTenMillion": "Сумма должна быть меньше 10 000 000.",
|
||||
"paidByRequired": "Пожалуйста, выберите участника.",
|
||||
"paidForMin1": "За этот расход должен заплатить как минимум один участник.",
|
||||
"noZeroShares": "Все доли должны быть больше 0.",
|
||||
"amountSum": "Сумма расхода должна быть равна сумме значений, распределенных между участниками.",
|
||||
"percentageSum": "Сумма процентов должна быть равна 100."
|
||||
},
|
||||
"Categories": {
|
||||
"search": "Поиск категорий...",
|
||||
"noCategory": "Категорий не нашлось.",
|
||||
"Uncategorized": {
|
||||
"heading": "Без категории",
|
||||
"General": "Общее",
|
||||
"Payment": "Выплата"
|
||||
},
|
||||
"Entertainment": {
|
||||
"heading": "Развлечения",
|
||||
"Entertainment": "Развлечения",
|
||||
"Games": "Игры",
|
||||
"Movies": "Кино",
|
||||
"Music": "Музыка",
|
||||
"Sports": "Спорт"
|
||||
},
|
||||
"Food and Drink": {
|
||||
"heading": "Еда и напитки",
|
||||
"Food and Drink": "Еда и напитки",
|
||||
"Dining Out": "Рестораны и кафе",
|
||||
"Groceries": "Продукты",
|
||||
"Liquor": "Напитки"
|
||||
},
|
||||
"Home": {
|
||||
"heading": "Дом",
|
||||
"Home": "Дом",
|
||||
"Electronics": "Электроника",
|
||||
"Furniture": "Мебель",
|
||||
"Household Supplies": "Расходные материалы",
|
||||
"Maintenance": "Уборка",
|
||||
"Mortgage": "Ипотека",
|
||||
"Pets": "Домашние животные",
|
||||
"Rent": "Аренда",
|
||||
"Services": "Коммунальные расходы"
|
||||
},
|
||||
"Life": {
|
||||
"heading": "Жизнь",
|
||||
"Childcare": "Дети",
|
||||
"Clothing": "Одежда",
|
||||
"Education": "Образование",
|
||||
"Gifts": "Подарки",
|
||||
"Insurance": "Страховки",
|
||||
"Medical Expenses": "Медицина",
|
||||
"Taxes": "Налоги"
|
||||
},
|
||||
"Transportation": {
|
||||
"heading": "Транспорт",
|
||||
"Transportation": "Транспорт",
|
||||
"Bicycle": "Велосипед",
|
||||
"Bus/Train": "Автобусы и поезда",
|
||||
"Car": "Авто",
|
||||
"Gas/Fuel": "Топливо",
|
||||
"Hotel": "Отели",
|
||||
"Parking": "Парковка",
|
||||
"Plane": "Самолеты",
|
||||
"Taxi": "Такси"
|
||||
},
|
||||
"Utilities": {
|
||||
"heading": "Коммунальные расходы",
|
||||
"Utilities": "Коммунальные расходы",
|
||||
"Cleaning": "Клининг",
|
||||
"Electricity": "Электричество",
|
||||
"Heat/Gas": "Отопление/Газ",
|
||||
"Trash": "Утилизация отходов",
|
||||
"TV/Phone/Internet": "ТВ/Телефон/Интернет",
|
||||
"Water": "Вода"
|
||||
}
|
||||
}
|
||||
}
|
||||
396
messages/zh-CN.json
Normal file
396
messages/zh-CN.json
Normal file
@@ -0,0 +1,396 @@
|
||||
{
|
||||
"Homepage": {
|
||||
"title": "与<strong>朋友和家人</strong>共享<strong>开支</strong>",
|
||||
"description": "欢迎使用你的全新<strong>Spliit</strong>实例!",
|
||||
"button": {
|
||||
"groups": "前往群组",
|
||||
"github": "GitHub"
|
||||
}
|
||||
},
|
||||
"Header": {
|
||||
"groups": "群组"
|
||||
},
|
||||
"Footer": {
|
||||
"madeIn": "Made in Montréal, Québec 🇨🇦",
|
||||
"builtBy": "由 <author>Sebastien Castiel</author> 以及 <source>社区贡献者们</source> 共同构建"
|
||||
},
|
||||
"Expenses": {
|
||||
"title": "消费",
|
||||
"description": "这里有你为你的群组创建的消费。",
|
||||
"create": "创建消费",
|
||||
"createFirst": "创建首个消费",
|
||||
"noExpenses": "你的群组内目前没有任何消费。",
|
||||
"exportJson": "导出到JSON",
|
||||
"searchPlaceholder": "查找消费……",
|
||||
"ActiveUserModal": {
|
||||
"title": "你是哪位?",
|
||||
"description": "告诉我们你在群组中的身份,以便定制你的信息呈现方式。",
|
||||
"nobody": "我不想选择任何人",
|
||||
"save": "保存变更",
|
||||
"footer": "此项设定之后可以在群组设定中修改。"
|
||||
},
|
||||
"Groups": {
|
||||
"upcoming": "即将到来",
|
||||
"thisWeek": "本周",
|
||||
"earlierThisMonth": "本月早些时候",
|
||||
"lastMonth": "上个月",
|
||||
"earlierThisYear": "本年早些时候",
|
||||
"lastYera": "去年",
|
||||
"older": "更早"
|
||||
}
|
||||
},
|
||||
"ExpenseCard": {
|
||||
"paidBy": "<strong>{paidBy}</strong> 为 <paidFor></paidFor> 支付。",
|
||||
"receivedBy": "<strong>{paidBy}</strong> 为 <paidFor></paidFor> 接收。",
|
||||
"yourBalance": "你的余额:"
|
||||
},
|
||||
"Groups": {
|
||||
"myGroups": "我的群组",
|
||||
"create": "创建",
|
||||
"loadingRecent": "加载最近的群组……",
|
||||
"NoRecent": {
|
||||
"description": "你最近没有访问任何群组。",
|
||||
"create": "创建一个群组",
|
||||
"orAsk": "或者让你的朋友发给你现有群组的链接。"
|
||||
},
|
||||
"recent": "最近的群组",
|
||||
"starred": "已收藏的群组",
|
||||
"archived": "已归档的群组",
|
||||
"archive": "归档群组",
|
||||
"unarchive": "取消归档群组",
|
||||
"removeRecent": "从最近的群组中删除",
|
||||
"RecentRemovedToast": {
|
||||
"title": "群组已删除",
|
||||
"description": "群组已从你的最近群组列表中删除。",
|
||||
"undoAlt": "撤销群组删除",
|
||||
"undo": "撤销"
|
||||
},
|
||||
"AddByURL": {
|
||||
"button": "使用URL添加",
|
||||
"title": "使用URL添加一个群组",
|
||||
"description": "如果你被分享了一个群组,你可以将群组的URL粘贴到这里以添加这个群组。",
|
||||
"error": "哎呀,我们没办法根据你的URL找到相应的群组……"
|
||||
},
|
||||
"NotFound": {
|
||||
"text": "该群组不存在。",
|
||||
"link": "跳转到最近访问过的群组"
|
||||
}
|
||||
},
|
||||
"GroupForm": {
|
||||
"title": "群组信息",
|
||||
"NameField": {
|
||||
"label": "群组名",
|
||||
"placeholder": "暑假",
|
||||
"description": "为你的群组输入一个名字。"
|
||||
},
|
||||
"InformationField": {
|
||||
"label": "群组信息",
|
||||
"placeholder": "哪些信息与群组成员有关?"
|
||||
},
|
||||
"CurrencyField": {
|
||||
"label": "货币标志",
|
||||
"placeholder": "$, €, £…",
|
||||
"description": "我们根据这个显示相应的货币金额。"
|
||||
},
|
||||
"Participants": {
|
||||
"title": "群组成员",
|
||||
"description": "输入每位成员的名字。",
|
||||
"protectedParticipant": "群组成员是消费的一部分,不可删除。",
|
||||
"new": "新建",
|
||||
"add": "添加群组成员",
|
||||
"John": "John",
|
||||
"Jane": "Jane",
|
||||
"Jack": "Jack"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "本地设定",
|
||||
"description": "这些设定是按设备设定的,用于定制你的使用体验。",
|
||||
"ActiveUserField": {
|
||||
"label": "当前用户",
|
||||
"placeholder": "选择一个群组成员",
|
||||
"none": "无",
|
||||
"description": "用于支付消费的默认用户。"
|
||||
},
|
||||
"save": "保存",
|
||||
"saving": "保存中……",
|
||||
"create": "创建",
|
||||
"creating": "创建中",
|
||||
"cancel": "取消"
|
||||
}
|
||||
},
|
||||
"ExpenseForm": {
|
||||
"Income": {
|
||||
"create": "创建收入",
|
||||
"edit": "编辑收入",
|
||||
"TitleField": {
|
||||
"label": "收入标题",
|
||||
"placeholder": "周一晚上的餐厅",
|
||||
"description": "描述这个收入。"
|
||||
},
|
||||
"DateField": {
|
||||
"label": "收入日期",
|
||||
"description": "输入收到这笔收入的日期。"
|
||||
},
|
||||
"categoryFieldDescription": "选择收入类别。",
|
||||
"paidByField": {
|
||||
"label": "接收到",
|
||||
"description": "选择接收到这笔收入的群组成员。"
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "接收给",
|
||||
"description": "选择收入是为谁而收。"
|
||||
},
|
||||
"splitModeDescription": "选择如何划分这笔收入。",
|
||||
"attachDescription": "查看并为这笔收入附加收据。"
|
||||
},
|
||||
"Expense": {
|
||||
"create": "创建消费",
|
||||
"edit": "编辑消费",
|
||||
"TitleField": {
|
||||
"label": "消费标题",
|
||||
"placeholder": "周一晚上的餐厅",
|
||||
"description": "描述这个消费。"
|
||||
},
|
||||
"DateField": {
|
||||
"label": "消费日期",
|
||||
"description": "输入支付这笔消费的日期。"
|
||||
},
|
||||
"categoryFieldDescription": "选择消费类别。",
|
||||
"paidByField": {
|
||||
"label": "支付自",
|
||||
"description": "选择支付这笔消费的群组成员。"
|
||||
},
|
||||
"paidFor": {
|
||||
"title": "支付给",
|
||||
"description": "选择消费是为谁而支出。"
|
||||
},
|
||||
"splitModeDescription": "选择如何划分这笔消费。",
|
||||
"attachDescription": "查看并为这笔消费附加收据。"
|
||||
},
|
||||
"amountField": {
|
||||
"label": "金额"
|
||||
},
|
||||
"isReimbursementField": {
|
||||
"label": "这是一笔报销款"
|
||||
},
|
||||
"categoryField": {
|
||||
"label": "类别"
|
||||
},
|
||||
"notesField": {
|
||||
"label": "附注"
|
||||
},
|
||||
"selectNone": "取消选中",
|
||||
"selectAll": "全选",
|
||||
"shares": "份额",
|
||||
"advancedOptions": "高级分账选项……",
|
||||
"SplitModeField": {
|
||||
"label": "分账模式",
|
||||
"evenly": "平均分配",
|
||||
"byShares": "按份额分配",
|
||||
"byPercentage": "按百分比分配",
|
||||
"byAmount": "按金额分配",
|
||||
"saveAsDefault": "保存为默认分账设置"
|
||||
},
|
||||
"DeletePopup": {
|
||||
"label": "删除",
|
||||
"title": "要删除这项消费吗?",
|
||||
"description": "你真的确定要删除这项消费吗?此行动不可撤销。",
|
||||
"yes": "确定",
|
||||
"cancel": "取消"
|
||||
},
|
||||
"attachDocuments": "附加文档",
|
||||
"create": "创建",
|
||||
"creating": "创建中……",
|
||||
"save": "保存",
|
||||
"saving": "保存中……",
|
||||
"cancel": "取消"
|
||||
},
|
||||
"ExpenseDocumentsInput": {
|
||||
"TooBigToast": {
|
||||
"title": "文件过大",
|
||||
"description": "可上传的最大文件大小为{maxSize},你的文件为${size}。"
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "上传文档时发生错误",
|
||||
"description": "上传文档时发生了一些错误。请稍后重试或更换文件。",
|
||||
"retry": "重试"
|
||||
}
|
||||
},
|
||||
"CreateFromReceipt": {
|
||||
"Dialog": {
|
||||
"triggerTitle": "从收据中创建消费",
|
||||
"title": "从收据中创建",
|
||||
"description": "从收据照片上提取消费信息。",
|
||||
"body": "上传收据的图片,我们会尽可能地从中扫描出消费信息。",
|
||||
"selectImage": "选择图片……",
|
||||
"titleLabel": "标题:",
|
||||
"categoryLabel": "类别:",
|
||||
"amountLabel": "金额:",
|
||||
"dateLabel": "日期:",
|
||||
"editNext": "你之后可以修改消费的信息。",
|
||||
"continue": "继续"
|
||||
},
|
||||
"unknown": "未知",
|
||||
"TooBigToast": {
|
||||
"title": "文件过大",
|
||||
"description": "可上传的最大文件大小为{maxSize},你的文件为${size}。"
|
||||
},
|
||||
"ErrorToast": {
|
||||
"title": "上传文档时发生错误",
|
||||
"description": "上传文档时发生了一些错误。请稍后重试或更换文件。",
|
||||
"retry": "重试"
|
||||
}
|
||||
},
|
||||
"Balances": {
|
||||
"title": "余额",
|
||||
"description": "这是每位群组成员支付或被支付的金额。",
|
||||
"Reimbursements": {
|
||||
"title": "建议报销",
|
||||
"description": "这里是优化群组成员之间报销的建议。",
|
||||
"noImbursements": "看起来你的群组不需要任何报销😁",
|
||||
"owes": "<strong>{from}</strong> 欠 <strong>{to}</strong>",
|
||||
"markAsPaid": "标记为已支付"
|
||||
}
|
||||
},
|
||||
"Stats": {
|
||||
"title": "统计",
|
||||
"Totals": {
|
||||
"title": "总计",
|
||||
"description": "整个群组的花费合计。",
|
||||
"groupSpendings": "群组总计开销",
|
||||
"groupEarnings": "群组总计收入",
|
||||
"yourSpendings": "你的总计开销",
|
||||
"yourEarnings": "你的总计收入",
|
||||
"yourShare": "你的总计份额"
|
||||
}
|
||||
},
|
||||
"Activity": {
|
||||
"title": "活动",
|
||||
"description": "该群组所有活动总览",
|
||||
"noActivity": "你的群组目前没有任何活动。",
|
||||
"someone": "某人",
|
||||
"settingsModified": "群组设定已被<strong>{participant}</strong>更改。",
|
||||
"expenseCreated": "消费 <em>{expense}</em> 由 <strong>{participant}</strong> 创建。",
|
||||
"expenseUpdated": "消费 <em>{expense}</em> 由 <strong>{participant}</strong> 更新。",
|
||||
"expenseDeleted": "消费 <em>{expense}</em> 由 <strong>{participant}</strong> 删除。",
|
||||
"Groups": {
|
||||
"today": "今天",
|
||||
"yesterday": "昨天",
|
||||
"earlierThisWeek": "这周早些时候",
|
||||
"lastWeek": "上周",
|
||||
"earlierThisMonth": "这月早些时候",
|
||||
"lastMonth": "上月",
|
||||
"earlierThisYear": "这年早些时候",
|
||||
"lastYear": "上年",
|
||||
"older": "更早"
|
||||
}
|
||||
},
|
||||
"Information": {
|
||||
"title": "信息",
|
||||
"description": "使用此处以添加与群组成员相关的任何信息。",
|
||||
"empty": "当前没有群组信息。"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "设定"
|
||||
},
|
||||
"Locale": {
|
||||
"en-US": "English",
|
||||
"fi": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"es": "Español",
|
||||
"de-DE": "Deutsch",
|
||||
"zh-CN": "Chinese (Simplified)",
|
||||
"ru-RU": "Русский"
|
||||
},
|
||||
"Share": {
|
||||
"title": "分享",
|
||||
"description": "请将此URL分享给其他群组成员,以使其可以查看群组并添加消费。",
|
||||
"warning": "警告!",
|
||||
"warningHelp": "任何持有群组URL的个体都有能够查看并编辑消费。请谨慎分享!"
|
||||
},
|
||||
"SchemaErrors": {
|
||||
"min1": "输入至少1个字符。",
|
||||
"min2": "输入至少2个字符。",
|
||||
"max5": "输入至少5个字符。",
|
||||
"max50": "输入至少50个字符。",
|
||||
"duplicateParticipantName": "此名字已被另一位群组成员占用。",
|
||||
"titleRequired": "请输入标题。",
|
||||
"invalidNumber": "无效数值。",
|
||||
"amountRequired": "你必须输入一个金额。",
|
||||
"amountNotZero": "金额不可以为0。",
|
||||
"amountTenMillion": "金额必须小于10,000,000。",
|
||||
"paidByRequired": "你必须选择一个群组成员。",
|
||||
"paidForMin1": "这项消费必须支付给至少1名群组成员。",
|
||||
"noZeroShares": "所有份额必须大于0。",
|
||||
"amountSum": "金额之和必须等于消费的金额。",
|
||||
"percentageSum": "百分比之和必须等于100。"
|
||||
},
|
||||
"Categories": {
|
||||
"search": "搜寻类别……",
|
||||
"noCategory": "未找到类别。",
|
||||
"Uncategorized": {
|
||||
"heading": "未分类",
|
||||
"General": "一般",
|
||||
"Payment": "支付"
|
||||
},
|
||||
"Entertainment": {
|
||||
"heading": "娱乐",
|
||||
"Entertainment": "娱乐",
|
||||
"Games": "游戏",
|
||||
"Movies": "电影",
|
||||
"Music": "音乐",
|
||||
"Sports": "运动"
|
||||
},
|
||||
"Food and Drink": {
|
||||
"heading": "饮食",
|
||||
"Food and Drink": "饮食",
|
||||
"Dining Out": "下馆子",
|
||||
"Groceries": "便利店",
|
||||
"Liquor": "酒水"
|
||||
},
|
||||
"Home": {
|
||||
"heading": "居家",
|
||||
"Home": "居家",
|
||||
"Electronics": "电费",
|
||||
"Furniture": "家具",
|
||||
"Household Supplies": "家庭日用品",
|
||||
"Maintenance": "维护",
|
||||
"Mortgage": "贷款",
|
||||
"Pets": "宠物",
|
||||
"Rent": "租金",
|
||||
"Services": "服务"
|
||||
},
|
||||
"Life": {
|
||||
"heading": "生活",
|
||||
"Childcare": "儿童保育",
|
||||
"Clothing": "衣物",
|
||||
"Education": "教育",
|
||||
"Gifts": "礼物",
|
||||
"Insurance": "保险",
|
||||
"Medical Expenses": "医疗支出",
|
||||
"Taxes": "税"
|
||||
},
|
||||
"Transportation": {
|
||||
"heading": "交通",
|
||||
"Transportation": "交通",
|
||||
"Bicycle": "自行车",
|
||||
"Bus/Train": "巴士/列车",
|
||||
"Car": "汽车",
|
||||
"Gas/Fuel": "燃料",
|
||||
"Hotel": "旅馆",
|
||||
"Parking": "停车",
|
||||
"Plane": "飞机",
|
||||
"Taxi": "出租车"
|
||||
},
|
||||
"Utilities": {
|
||||
"heading": "日常账单",
|
||||
"Utilities": "日常账单",
|
||||
"Cleaning": "清洁费",
|
||||
"Electricity": "电费",
|
||||
"Heat/Gas": "暖气/瓦斯",
|
||||
"Trash": "垃圾",
|
||||
"TV/Phone/Internet": "电视/手机/互联网",
|
||||
"Water": "水"
|
||||
}
|
||||
}
|
||||
}
|
||||
4080
package-lock.json
generated
4080
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -12,7 +12,8 @@
|
||||
"prettier": "prettier -w src",
|
||||
"postinstall": "prisma migrate deploy && prisma generate",
|
||||
"build-image": "./scripts/build-image.sh",
|
||||
"start-container": "docker compose --env-file container.env up"
|
||||
"start-container": "docker compose --env-file container.env up",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@formatjs/intl-localematcher": "^0.5.4",
|
||||
@@ -62,8 +63,12 @@
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/dom": "^10.4.0",
|
||||
"@testing-library/jest-dom": "^6.4.8",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@total-typescript/ts-reset": "^0.5.1",
|
||||
"@types/content-disposition": "^0.5.8",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/negotiator": "^0.6.3",
|
||||
"@types/node": "^20",
|
||||
"@types/pg": "^8.10.9",
|
||||
@@ -74,10 +79,13 @@
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "^14.1.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"postcss": "^8",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier-plugin-organize-imports": "^3.2.3",
|
||||
"tailwindcss": "^3",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export async function extractExpenseInformationFromImage(imageUrl: string) {
|
||||
const categories = await getCategories()
|
||||
|
||||
const body: ChatCompletionCreateParamsNonStreaming = {
|
||||
model: 'gpt-4-vision-preview',
|
||||
model: 'gpt-4-turbo',
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
|
||||
@@ -206,6 +206,7 @@ export function CreateFromReceiptButton({
|
||||
groupCurrency,
|
||||
receiptInfo.amount,
|
||||
locale,
|
||||
true,
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -1,31 +1,35 @@
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Github } from 'lucide-react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import Link from 'next/link'
|
||||
|
||||
// FIX for https://github.com/vercel/next.js/issues/58615
|
||||
// export const dynamic = 'force-dynamic'
|
||||
|
||||
export default function HomePage() {
|
||||
const t = useTranslations()
|
||||
return (
|
||||
<main>
|
||||
<section className="py-16 md:py-24 lg:py-32">
|
||||
<div className="container flex max-w-screen-md flex-col items-center gap-4 text-center">
|
||||
<h1 className="!leading-none font-bold text-3xl sm:text-5xl md:text-6xl lg:text-7xl landing-header py-2">
|
||||
Share <strong>Expenses</strong> <br /> with <strong>Friends</strong>{' '}
|
||||
& <strong>Family</strong>
|
||||
<h1 className="!leading-none font-bold text-2xl sm:text-3xl md:text-4xl lg:text-5xl landing-header py-2">
|
||||
{t.rich('Homepage.title', {
|
||||
strong: (chunks) => <strong>{chunks}</strong>,
|
||||
})}
|
||||
</h1>
|
||||
<p className="max-w-[42rem] leading-normal text-muted-foreground sm:text-xl sm:leading-8">
|
||||
Welcome to your new <strong>Spliit</strong> instance! <br />
|
||||
Customize this page by editing <em>src/app/page.tsx</em>.
|
||||
{t.rich('Homepage.description', {
|
||||
strong: (chunks) => <strong>{chunks}</strong>,
|
||||
})}
|
||||
</p>
|
||||
<div className="flex gap-2">
|
||||
<Button asChild>
|
||||
<Link href="/groups">Go to groups</Link>
|
||||
<Link href="/groups">{t('Homepage.button.groups')}</Link>
|
||||
</Button>
|
||||
<Button asChild variant="secondary">
|
||||
<Link href="https://github.com/spliit-app/spliit">
|
||||
<Github className="w-4 h-4 mr-2" />
|
||||
GitHub
|
||||
{t('Homepage.button.github')}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -253,28 +253,21 @@ export function ExpenseForm({
|
||||
|
||||
useEffect(() => {
|
||||
setManuallyEditedParticipants(new Set())
|
||||
const newPaidFor = defaultSplittingOptions.paidFor.map((participant) => ({
|
||||
...participant,
|
||||
shares: String(participant.shares) as unknown as number,
|
||||
}))
|
||||
form.setValue('paidFor', newPaidFor, { shouldValidate: true })
|
||||
}, [form.watch('splitMode'), form.watch('amount')])
|
||||
|
||||
useEffect(() => {
|
||||
const totalAmount = Number(form.getValues().amount) || 0
|
||||
const paidFor = form.getValues().paidFor
|
||||
const splitMode = form.getValues().splitMode
|
||||
|
||||
let newPaidFor = [...paidFor]
|
||||
|
||||
// Only auto-balance for split mode 'Unevenly - By amount'
|
||||
if (
|
||||
splitMode === 'EVENLY' ||
|
||||
splitMode === 'BY_SHARES' ||
|
||||
splitMode === 'BY_PERCENTAGE'
|
||||
splitMode === 'BY_AMOUNT' &&
|
||||
(form.getFieldState('paidFor').isDirty ||
|
||||
form.getFieldState('amount').isDirty)
|
||||
) {
|
||||
return
|
||||
} else {
|
||||
// Only auto-balance for split mode 'Unevenly - By amount'
|
||||
const totalAmount = Number(form.getValues().amount) || 0
|
||||
const paidFor = form.getValues().paidFor
|
||||
let newPaidFor = [...paidFor]
|
||||
|
||||
const editedParticipants = Array.from(manuallyEditedParticipants)
|
||||
let remainingAmount = totalAmount
|
||||
let remainingParticipants = newPaidFor.length - editedParticipants.length
|
||||
@@ -569,18 +562,29 @@ export function ExpenseForm({
|
||||
({ participant }) => participant === id,
|
||||
)}
|
||||
onCheckedChange={(checked) => {
|
||||
return checked
|
||||
? field.onChange([
|
||||
...field.value,
|
||||
{
|
||||
participant: id,
|
||||
shares: '1',
|
||||
},
|
||||
])
|
||||
: field.onChange(
|
||||
const options = {
|
||||
shouldDirty: true,
|
||||
shouldTouch: true,
|
||||
shouldValidate: true,
|
||||
}
|
||||
checked
|
||||
? form.setValue(
|
||||
'paidFor',
|
||||
[
|
||||
...field.value,
|
||||
{
|
||||
participant: id,
|
||||
shares: '1' as unknown as number,
|
||||
},
|
||||
],
|
||||
options,
|
||||
)
|
||||
: form.setValue(
|
||||
'paidFor',
|
||||
field.value?.filter(
|
||||
(value) => value.participant !== id,
|
||||
),
|
||||
options,
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -79,7 +79,7 @@ const FormItem = React.forwardRef<
|
||||
|
||||
return (
|
||||
<FormItemContext.Provider value={{ id }}>
|
||||
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
||||
<div ref={ref} className={cn("col-span-2 md:col-span-1 space-y-2", className)} {...props} />
|
||||
</FormItemContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
10
src/i18n.ts
10
src/i18n.ts
@@ -1,7 +1,15 @@
|
||||
import { getRequestConfig } from 'next-intl/server'
|
||||
import { getUserLocale } from './lib/locale'
|
||||
|
||||
export const locales = ['en-US', 'fi'] as const
|
||||
export const locales = [
|
||||
'en-US',
|
||||
'fi',
|
||||
'fr-FR',
|
||||
'es',
|
||||
'de-DE',
|
||||
'zh-CN',
|
||||
'ru-RU',
|
||||
] as const
|
||||
export type Locale = (typeof locales)[number]
|
||||
export type Locales = ReadonlyArray<Locale>
|
||||
export const defaultLocale: Locale = 'en-US'
|
||||
|
||||
71
src/lib/utils.test.ts
Normal file
71
src/lib/utils.test.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { formatCurrency } from './utils'
|
||||
|
||||
describe('formatCurrency', () => {
|
||||
const currency = 'CUR'
|
||||
/** For testing decimals */
|
||||
const partialAmount = 1.23
|
||||
/** For testing small full amounts */
|
||||
const smallAmount = 1
|
||||
/** For testing large full amounts */
|
||||
const largeAmount = 10000
|
||||
|
||||
/** Non-breaking space */
|
||||
const nbsp = '\xa0'
|
||||
|
||||
interface variation {
|
||||
amount: number
|
||||
locale: string
|
||||
result: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Variations to be tested, chosen as follows
|
||||
* - `en-US` is a very common i18n fallback
|
||||
* - `de-DE` exhibited faulty behavior in previous versions
|
||||
*/
|
||||
const variations: variation[] = [
|
||||
{
|
||||
amount: partialAmount,
|
||||
locale: `en-US`,
|
||||
result: `${currency}1.23`,
|
||||
},
|
||||
{
|
||||
amount: smallAmount,
|
||||
locale: `en-US`,
|
||||
result: `${currency}1.00`,
|
||||
},
|
||||
{
|
||||
amount: largeAmount,
|
||||
locale: `en-US`,
|
||||
result: `${currency}10,000.00`,
|
||||
},
|
||||
{
|
||||
amount: partialAmount,
|
||||
locale: `de-DE`,
|
||||
result: `1,23${nbsp}${currency}`,
|
||||
},
|
||||
{
|
||||
amount: smallAmount,
|
||||
locale: `de-DE`,
|
||||
result: `1,00${nbsp}${currency}`,
|
||||
},
|
||||
{
|
||||
amount: largeAmount,
|
||||
locale: `de-DE`,
|
||||
result: `10.000,00${nbsp}${currency}`,
|
||||
},
|
||||
]
|
||||
|
||||
for (const variation of variations) {
|
||||
it(`formats ${variation.amount} in ${variation.locale} without fractions`, () => {
|
||||
expect(
|
||||
formatCurrency(currency, variation.amount * 100, variation.locale),
|
||||
).toBe(variation.result)
|
||||
})
|
||||
it(`formats ${variation.amount} in ${variation.locale} with fractions`, () => {
|
||||
expect(
|
||||
formatCurrency(currency, variation.amount, variation.locale, true),
|
||||
).toBe(variation.result)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -28,10 +28,16 @@ export function formatCategoryForAIPrompt(category: Category) {
|
||||
return `"${category.grouping}/${category.name}" (ID: ${category.id})`
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fractions Financial values in this app are generally processed in cents (or equivalent).
|
||||
* They are are therefore integer representations of the amount (e.g. 100 for USD 1.00).
|
||||
* Set this to `true` if you need to pass a value with decimal fractions instead (e.g. 1.00 for USD 1.00).
|
||||
*/
|
||||
export function formatCurrency(
|
||||
currency: string,
|
||||
amount: number,
|
||||
locale: string,
|
||||
fractions?: boolean,
|
||||
) {
|
||||
const format = new Intl.NumberFormat(locale, {
|
||||
minimumFractionDigits: 2,
|
||||
@@ -40,7 +46,7 @@ export function formatCurrency(
|
||||
// '€' will be placed in correct position
|
||||
currency: 'EUR',
|
||||
})
|
||||
const formattedAmount = format.format(amount / 100)
|
||||
const formattedAmount = format.format(fractions ? amount : amount / 100)
|
||||
return formattedAmount.replace('€', currency)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user