Add Russian i18n with DB translations, locale API, and curator review UI.

UI chrome via react-i18next, catalog text in entity_translations with ru.wikipedia seeding, locale-aware search, and Translations page for publish workflow.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Danila Khodjaef
2026-07-15 11:51:46 +03:00
co-authored by Cursor
parent f247b418d8
commit ca58c43648
51 changed files with 2252 additions and 101 deletions
+10
View File
@@ -0,0 +1,10 @@
{
"title": "Art history notes",
"readSource": "Read source",
"categoryTechnique": "Technique",
"categoryComposition": "Composition",
"categorySubject": "Subject",
"categorySymbolism": "Symbolism",
"categoryHistorical": "Historical context",
"categoryOther": "Notes"
}
+6
View File
@@ -0,0 +1,6 @@
{
"enterGallery": "Enter Gallery",
"noBio": "No biography available yet.",
"wikipediaSource": "Text adapted from Wikipedia",
"backToTimeline": "← Back to Timeline"
}
+13
View File
@@ -0,0 +1,13 @@
{
"loading": "Loading…",
"close": "Close",
"back": "Back",
"save": "Save",
"cancel": "Cancel",
"yes": "Yes",
"no": "No",
"error": "Something went wrong",
"localeEn": "EN",
"localeRu": "RU",
"language": "Language"
}
+14
View File
@@ -0,0 +1,14 @@
{
"checked": "Checked",
"fixIt": "Fix it",
"more": "More",
"clear": "Clear",
"upload": "Upload",
"searching": "Searching…",
"saving": "Saving…",
"loginTitle": "Curator login",
"username": "Username",
"password": "Password",
"signIn": "Sign in",
"loginFailed": "Login failed"
}
+14
View File
@@ -0,0 +1,14 @@
{
"backToTimeline": "← Back to Timeline",
"exitToTimeline": "Exit to Timeline",
"loadingGallery": "Loading gallery…",
"instructionsTitle": "Gallery controls",
"instructionMove": "Drag to look around",
"instructionZoom": "Scroll to zoom",
"instructionClick": "Click a painting to view details",
"wingOf": "Wing {{current}} of {{total}}",
"exitConfirmTitle": "Leave gallery?",
"exitConfirmBody": "Return to the timeline or stay in the hall.",
"stay": "Stay",
"exit": "Exit"
}
+20
View File
@@ -0,0 +1,20 @@
{
"title": "Virtual Art Gallery",
"subtitle": "Explore art history on an interactive timeline — enter 3D galleries and discover connections between artists and masterpieces.",
"loadingArtHistory": "Loading art history…",
"loadingPortraits": "Loading portraits…",
"openingArtistGallery": "Opening artist gallery…",
"openingMovementGallery": "Opening movement gallery…",
"backToTimeline": "← Back to Timeline",
"backToGallery": "← Back to Gallery",
"curatorLogin": "Curator login",
"curatorLogout": "Log out",
"signedInAs": "Signed in as {{username}}",
"debugMode": "Debug mode",
"showMoreDebug": "Show more (debug)",
"checkup": "Checkup",
"translations": "Translations",
"curatorRequiredTitle": "Curator access required",
"curatorRequiredBody": "Sign in as a curator to use this tool.",
"backToGalleryBtn": "Back to gallery"
}
+11
View File
@@ -0,0 +1,11 @@
{
"aboutArtist": "About {{name}}",
"influencedBy": "Influenced By",
"influenced": "Influenced",
"noInfluences": "No documented influences for this work.",
"noInfluencedWorks": "No documented works influenced by this painting yet.",
"catalogPosition": "Catalog position",
"lightboxHint": "Click anywhere to close",
"prevPainting": "Previous painting",
"nextPainting": "Next painting"
}
+10
View File
@@ -0,0 +1,10 @@
{
"label": "Search",
"placeholder": "Search artists, paintings, movements…",
"resultsLabel": "Search results",
"noMatches": "No matches found.",
"groupArtist": "Artists",
"groupMovement": "Movements",
"groupPainting": "Paintings",
"searchFailed": "Search failed"
}
+20
View File
@@ -0,0 +1,20 @@
{
"title": "Translation review",
"back": "← Back to gallery",
"locale": "Locale",
"entityType": "Entity type",
"status": "Status",
"all": "All",
"draft": "Draft",
"reviewed": "Reviewed",
"published": "Published",
"coverage": "Coverage",
"artistsBio": "Artists with bio (ru)",
"paintingsTitle": "Paintings with title alias (ru)",
"canonical": "English (canonical)",
"translation": "Translation",
"saveDraft": "Save draft",
"publish": "Publish",
"noRows": "No translation rows match the filter.",
"loadFailed": "Failed to load translations"
}