feat(localization): expand language support and enhance UI for user settings
All checks were successful
Deploy to production / deploy (push) Successful in 3m0s

- Added support for additional UI locales including Cebuano and Spanish, improving accessibility for a broader user base.
- Updated language selection components in the AppHeader and SettingsWidget to reflect new language options, enhancing user experience.
- Enhanced localization of various UI elements across components, ensuring consistent language representation and improved user engagement.
- Implemented logic to synchronize user language preferences with backend settings, providing a seamless experience when changing languages.
This commit is contained in:
Torsten Schulz (local)
2026-04-02 07:54:44 +02:00
parent ac5d436a36
commit 6d9d69dc10
72 changed files with 1792 additions and 343 deletions

View File

@@ -381,6 +381,10 @@
"sale": {
"runningGuards": "Guards"
},
"storage": {
"buyPartialError": "Error while buying part of the storage capacity.",
"sellError": "Error while selling storage capacity."
},
"production": {
"title": "Production",
"info": "Details about production in the branch.",

View File

@@ -1,6 +1,12 @@
{
"friends": {
"kicker": "Community",
"intro": "Friendships, open requests, and ongoing contacts in one place.",
"title": "Friends",
"stats": {
"existing": "Existing",
"open": "Open"
},
"tabs": {
"existing": "Existing",
"rejected": "Rejected",

View File

@@ -41,6 +41,59 @@
"message": {
"close": "Close"
},
"appShell": {
"header": {
"tagline": "Community platform",
"beta": "Beta",
"backend": "Backend",
"daemon": "Daemon",
"language": "Language"
},
"footer": {
"systemLabel": "System",
"noOpenDialogs": "No open dialogs",
"activeWindows": "{count} windows active",
"systemReady": "System ready",
"systemStatusUnavailable": "System status is not directly available in this view right now."
}
},
"widgets": {
"dashboard": {
"dragHandle": "Move",
"loading": "Loading..."
},
"birthdays": {
"today": "Today!",
"tomorrow": "Tomorrow",
"turningAge": "(turning {age})",
"inDays": "{count} days",
"empty": "No visible birthdays from friends"
},
"upcoming": {
"today": "Today",
"tomorrow": "Tomorrow",
"timeAt": "{time}",
"allDay": "All day",
"empty": "No upcoming appointments"
},
"appointments": {
"title": "📅 Appointments",
"loading": "Loading appointments...",
"empty": "No upcoming appointments",
"loadError": "Appointments could not be loaded"
},
"list": {
"noEntries": "No entries",
"entriesCount": "({count} entries)",
"fieldsCount": "({count} fields)"
},
"news": {
"emptyValue": "—"
},
"falukant": {
"emptyValue": "—"
}
},
"gender": {
"male": "Male",
"female": "Female",

View File

@@ -1,5 +1,54 @@
{
"home": {
"dashboard": {
"kicker": "Your area",
"title": "Welcome back!",
"subtitle": "Your personal entry point to community, appointments, Falukant, and ongoing activity.",
"edit": "Edit dashboard",
"addWidget": "+ Add widget ...",
"addAgain": "Add again",
"done": "Done",
"sectionTitle": "Your overview",
"sectionIntro": "Widgets can be moved and adjusted in edit mode.",
"widgetTitlePlaceholder": "Title",
"removeWidget": "Remove widget",
"remove": "Remove",
"empty": "No widgets yet. Click “Edit dashboard” and then “+ Add widget”.",
"defaultAppointmentsWidget": "Appointments",
"loadError": "Dashboard could not be loaded.",
"saveError": "Dashboard could not be saved.",
"widgetLabels": {
"appointments": "Appointments",
"falukant": "Falukant",
"news": "News",
"birthdays": "Birthdays",
"upcoming": "Upcoming appointments",
"calendar": "Calendar"
},
"overview": {
"activeWidgetsLabel": "Active widgets",
"activeWidgetsText": "Your dashboard is modular and can be rearranged at any time.",
"availableModulesLabel": "Available modules",
"availableModulesText": "You can combine community, calendar, news, and Falukant modules.",
"editModeLabel": "Edit mode",
"editModeActive": "Active",
"editModeInactive": "Off",
"editModeActiveText": "Widgets can currently be added and adjusted.",
"editModeInactiveText": "Content stays focused and calm to read."
}
},
"vocabLanding": {
"eyebrow": "Learn languages online",
"title": "The vocabulary trainer on YourPart combines learning, courses, and practice in one platform.",
"lead": "Work with interactive lessons, grow your vocabulary, and use structured content for a motivating learning flow right in the browser.",
"cta": "Start for free",
"feature1Title": "Interactive courses",
"feature1Text": "Courses, lessons, and exercises help you build new language skills step by step.",
"feature2Title": "Practice-focused",
"feature2Text": "Vocabulary, grammar, and review are aligned with an everyday learning routine.",
"feature3Title": "Part of a community",
"feature3Text": "The language area is embedded in a larger community platform with blogs, forum, and chat."
},
"betaNoticeLabel": "Beta notice:",
"betaNoticeText": "YourPart is under active development. Features may be incomplete, information may still be missing and things can change.",
"nologin": {

View File

@@ -2,6 +2,8 @@
"personal": {
"calendar": {
"title": "Calendar",
"kicker": "Planning",
"intro": "Appointments, birthdays, and your own entries in one structured overview.",
"today": "Today",
"newEntry": "New Entry",
"editEntry": "Edit Entry",

View File

@@ -57,7 +57,8 @@
"language": {
"de": "German",
"en": "English",
"ceb": "Bisaya"
"ceb": "Bisaya",
"es": "Spanish"
},
"eyecolor": {
"blue": "Blue",

View File

@@ -1,6 +1,11 @@
{
"socialnetwork": {
"usersearch": {
"kicker": "Community search",
"intro": "Find suitable contacts in the community by name, age, and gender.",
"ageSeparator": "to",
"resultsCount": "{count} results",
"openProfile": "Open profile",
"title": "User Search",
"username": "Username",
"age_from": "Age from",
@@ -120,7 +125,8 @@
"hideInput": "Hide new entry",
"imageUpload": "Image",
"submit": "Submit entry",
"noEntries": "No entries found"
"noEntries": "No entries found",
"entryImageAlt": "Guestbook entry image"
},
"interestedInGender": "Interested in",
"hasChildren": "Has children",
@@ -147,6 +153,8 @@
"weight": "Weight"
},
"gallery": {
"kicker": "Images and folders",
"intro": "Organize your own content, control visibility, and structure it in folders.",
"title": "Gallery",
"folders": "Folders",
"create_folder": "Create folder",
@@ -189,15 +197,22 @@
},
"show_image_dialog": {
"title": "Image"
}
},
"imagePreviewAlt": "Image preview",
"imageLoadingAlt": "Loading image"
},
"guestbook": {
"kicker": "Guestbook",
"intro": "Messages, feedback, and small glimpses from your network.",
"title": "Guestbook",
"prevPage": "Back",
"nextPage": "Next",
"page": "Page"
},
"diary": {
"kicker": "Personal entries",
"intro": "Thoughts, notes, and short updates in a calm personal view.",
"placeholder": "Write your diary entry...",
"title": "Diary",
"noEntries": "You haven't made any diary entries yet.",
"newEntry": "New diary entry",
@@ -213,6 +228,16 @@
"page": "Page"
},
"forum": {
"kicker": "Community forum",
"intro": "Topics, discussions, and new posts in one structured place.",
"createTitle": "Write a new topic",
"createIntro": "Set the title first, then write the post and publish it directly.",
"cancelCreation": "Cancel",
"creationHint": "Title and content must both be filled in.",
"communityFallback": "Community",
"topicIntro": "Discussions, replies, and new posts in a focused reading view.",
"topicCreated": "Topic created successfully.",
"topicCreateError": "Error creating topic",
"title": "Forum",
"showNewTopic": "Create new topic",
"hideNewTopic": "Cancel creation",
@@ -277,9 +302,32 @@
"videoUploadHint": "Upload videos for your unlocked erotic area here and maintain title and description directly during upload.",
"videoDescription": "Description",
"videoFile": "Video file",
"videoFormats": "MP4, WEBM, OGG, MOV",
"myVideos": "My videos",
"sharedVideos": "Shared videos",
"foreignVideosIntro": "Shared videos from the adult area.",
"foreignVideosOnlyHint": "You only see videos here that were shared with you for the adult area.",
"sharedVideosIntro": "Visible videos from shared adult areas.",
"noSharedVideos": "There are currently no shared videos available for you.",
"libraryTitle": "Library",
"libraryIntro": "Your uploads, visibility settings, and reports in one place.",
"libraryEmptyHint": "Create your first video on the left and manage it here afterwards in the library.",
"latestUpload": "Latest upload",
"visibleVideos": "Visible videos",
"moderationCases": "Moderation cases",
"notesTitle": "Notes",
"friendsVisibilityHint": "Friends can only see content if they are adults and unlocked for the adult area.",
"selectedUsersVisibilityHint": "Specifically shared people must also be adults and unlocked.",
"selectedUsersPlaceholder": "anna, bert, clara",
"imagePreviewAlt": "Image preview",
"imageLoadingAlt": "Loading image",
"untitled": "Untitled",
"noUploadYet": "No upload yet",
"closeEditing": "Close editing",
"editVisibility": "Edit visibility",
"noVideos": "You have not uploaded any erotic videos yet.",
"reportAction": "Report",
"reportHint": "Use {action} directly on the respective item when content should be reviewed.",
"reportNote": "Short note for moderation",
"submitReport": "Submit report",
"reportSubmitted": "The report has been submitted.",
@@ -323,6 +371,36 @@
"vocab": {
"title": "Vocabulary trainer",
"description": "Create languages (or subscribe to them) and share them with friends.",
"heroEyebrow": "Language learning",
"summaryTotalLabel": "Languages total",
"summaryTotalIntro": "All active language areas where you use or manage content.",
"summaryOwnedLabel": "Owned areas",
"summaryOwnedIntro": "This is where you actively create content, chapters, and learning material yourself.",
"summarySubscribedLabel": "Subscribed",
"summarySubscribedIntro": "These areas are more about learning and progress than administration.",
"taskCreateEyebrow": "Quick start",
"taskCreateTitle": "Create new language",
"taskCreateIntro": "The best starting point if you want to structure and maintain content yourself.",
"taskContinueEyebrow": "Continue learning",
"taskContinueTitle": "Open courses and chapters",
"taskContinueIntro": "Jump straight into existing learning paths and continue with available courses.",
"ownedSectionTitle": "Owned languages",
"ownedSectionIntro": "Direct access to editing, chapters, and course management.",
"ownedHint": "Manage and maintain content",
"ownedEmpty": "No owned language areas yet.",
"subscribedSectionTitle": "Subscribed languages",
"subscribedSectionIntro": "Good for quickly getting back into learning without admin overhead.",
"subscribedHint": "Learn, practice, and review progress",
"subscribedEmpty": "No subscribed languages available.",
"languageHeroEyebrow": "Language",
"languageHeroIntro": "Chapters, search tools, and sharing for this language in one place.",
"newLanguageHeroEyebrow": "Vocabulary trainer",
"newLanguageHeroIntro": "Create a new language, generate a share code, and jump straight into editing.",
"newLanguageNameHint": "A short, clear language name is enough to get started.",
"newLanguageNameValidation": "The name should have at least 2 characters.",
"subscribeHeroEyebrow": "Vocabulary trainer",
"chapterHeroEyebrow": "Vocabulary trainer",
"chapterHeroIntro": "Browse chapter content, maintain vocabulary, and jump directly into practice.",
"newLanguage": "New language",
"newLanguageTitle": "Create new language",
"languageName": "Language name",
@@ -570,7 +648,91 @@
"languageAssistantPatternHint": "Focus especially on this pattern",
"languageAssistantPresetPracticeStart": "Let's practice a short everyday dialogue for the lesson \"{lesson}\". Please ask me questions and wait for my answers.",
"languageAssistantPresetCorrectStart": "I want to write my own sentences for the lesson \"{lesson}\". Please correct my answers briefly and clearly.",
"thisLesson": "this lesson"
"thisLesson": "this lesson",
"courseKicker": "Learning course",
"courseListKicker": "Courses",
"courseListIntro": "Filter public and your own learning courses, find the right one, and continue directly.",
"courseShareCodePlaceholder": "e.g. abc123def456",
"courseFlowEyebrow": "Daily flow",
"courseFlowTitle": "Best next step for today",
"courseFlowIntro": "The order follows the concept: due reviews first, then the current block, then intensive review, and finally free practice.",
"courseFlowReviewStat": "Due review: {count}",
"courseFlowBlockStat": "Active block: {block}",
"courseFlowReviewTitle": "Due review",
"courseFlowReviewDescription": "Lessons already completed that should come back today.",
"courseFlowReviewEmpty": "No older lesson is marked as due for review today.",
"courseFlowBlockTitle": "Current block",
"courseFlowBlockDescription": "This is where the next regular progress step in the course lives.",
"courseFlowBlockEmpty": "The current block is already done or there is no open block lesson right now.",
"courseFlowIntensiveTitle": "Due intensive review",
"courseFlowIntensiveDescription": "Condensed review once the block before it is mostly stable.",
"courseFlowIntensiveEmpty": "No new intensive review is unlocked right now.",
"courseFlowPracticeTitle": "Free practice",
"courseFlowPracticeDescription": "Completed lessons for relaxed extra practice outside the required path.",
"courseFlowPracticeEmpty": "As soon as you complete your first lessons, they will appear here for free practice.",
"practiceInTrainer": "Practice in trainer",
"lessonsCount": "{count} lessons",
"lessonBlockLabel": "Block {number}",
"lessonIntensiveBadge": "Intensive review",
"addLessonValidation": "Please provide number, title, and chapter.",
"addLessonSuccess": "Lesson created successfully.",
"addLessonError": "Could not add the lesson.",
"createCourseError": "Could not create the course.",
"deleteLessonTitle": "Delete lesson",
"deleteLessonSuccess": "Lesson deleted successfully.",
"deleteLessonError": "Could not delete the lesson.",
"enrollCourseError": "Could not enroll in the course.",
"editLessonPending": "Editing individual lessons is still pending.",
"timeToday": "today",
"timeSinceOneDay": "since 1 day",
"timeSinceDays": "since {count} days",
"reviewDueNow": "due now",
"reviewDueTomorrow": "due tomorrow",
"reviewDueInDays": "due in {count} days",
"reviewDueToday": "due today",
"reviewDueSinceOneDay": "due since 1 day",
"reviewDueSinceDays": "due since {count} days",
"reviewStageDay1": "Day 1",
"reviewStageDay3": "Day 3",
"reviewStageDay7": "Day 7",
"reviewStageCompleted": "Review completed",
"phaseQuickstart": "Quick start",
"phaseDailyLife": "Daily life",
"phaseStabilization": "Stabilization",
"phaseDefault": "Learning phase",
"didacticModeCoreInput": "New content",
"didacticModeGuidedDialogue": "Guided dialogue",
"didacticModeContrastTraining": "Contrast training",
"didacticModePatternDrill": "Pattern drill",
"didacticModeRealLifeScenario": "Real-life scenario",
"didacticModeIntensiveReview": "Review phase",
"didacticModeCheckpoint": "Checkpoint",
"didacticModeDefault": "Learning unit",
"didacticModeFocusDefault": "Learning focus",
"lessonMetaFocus": "Focus",
"lessonMetaPhase": "Phase",
"lessonMetaNewUnits": "New units",
"lessonMetaReview": "Review",
"intensiveReviewTitle": "Intensive review phase",
"intensiveReviewIntro": "This lesson prioritizes review and consolidation. New material is intentionally reduced so existing patterns can stabilize.",
"reviewPriorityTitle": "Review is mixed in step by step",
"reviewPriorityIntro": "The focus starts on the new terms of this lesson. As you progress, older vocabulary is gradually mixed in.",
"exerciseLockTitle": "Chapter test still locked",
"trainerStartWithReview": "Start with the new vocabulary from this lesson. As you practice, the trainer will automatically mix in fitting review items.",
"startLesson": "Start lesson",
"trainerProgressNewContent": "New content: {current}/{target}",
"trainerProgressReview": "Review: {count}",
"trainerProgressMixShare": "Mixed share: {percent}%",
"unknownExerciseTypeNotice": "This exercise type is not displayed interactively in the current view yet.",
"unknownExerciseTypeLabel": "Type: {type}",
"lessonReviewHeadlineDone": "This lesson has reached the free practice stage.",
"lessonReviewHeadlineDue": "This review wave is due now.",
"lessonReviewHeadlineScheduled": "This lesson is scheduled for the next review wave.",
"lessonReviewHintDone": "The 1/3/7-day review cycle is complete. You can now continue practicing this lesson freely.",
"lessonReviewHintNextDue": "Next due date: {due}.",
"reviewTimeNow": "now",
"reviewTimeTomorrow": "tomorrow",
"reviewTimeInDays": "in {count} days"
}
}
}