From 3ec5edf315b0568af5654098db64fa75112776c0 Mon Sep 17 00:00:00 2001 From: Sumit Dahal Date: Thu, 20 Aug 2026 13:35:42 +0545 Subject: [PATCH 1/4] fix: dedupe react-intl message ids breaking yarn build-locales --- frontend/src/components/badges/messages.js | 28 +++++++++++++------ frontend/src/components/header/messages.js | 4 --- frontend/src/components/levels/messages.js | 22 +++++++++++---- .../src/components/projectEdit/messages.js | 6 ++-- .../src/components/taskSelection/messages.js | 2 +- 5 files changed, 39 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/badges/messages.js b/frontend/src/components/badges/messages.js index 827aea21d7..03587d043a 100644 --- a/frontend/src/components/badges/messages.js +++ b/frontend/src/components/badges/messages.js @@ -1,30 +1,40 @@ import { defineMessages } from 'react-intl'; -export default defineMessages({ - add: { id: 'management.fields.managers.add', defaultMessage: 'Add' }, +import managementMessages from '../teamsAndOrgs/messages'; + +const ownMessages = defineMessages({ badgeInfo: { id: 'management.titles.badge_information', defaultMessage: 'Badge information' }, - badges: { id: 'management.badges', defaultMessage: 'Badges' }, building: { id: 'management.badges.building', defaultMessage: 'buildings added' }, - cancel: { id: 'management.button.cancel', defaultMessage: 'Cancel' }, changeset: { id: 'management.badges.changeset', defaultMessage: 'Number of changesets' }, changesets: { id: 'management.badges.changesets', defaultMessage: 'Changesets' }, - description: { id: 'management.fields.description', defaultMessage: 'Description' }, hidden: { id: 'management.badges.hidden', defaultMessage: 'Hide this badge from users' }, highway: { id: 'management.badges.highway', defaultMessage: 'km of highways added' }, road: { id: 'management.badges.road', defaultMessage: 'km of roads added' }, - image: { id: 'management.fields.organisation.image', defaultMessage: 'Image' }, imageError: { id: 'management.badges.imageError', defaultMessage: 'Error uploading image' }, - manage: { id: 'management.link.manage', defaultMessage: 'Manage {entity}' }, metric: { id: 'management.badges.metric', defaultMessage: 'Metric' }, - name: { id: 'management.fields.name', defaultMessage: 'Name' }, needsRequirements: { id: 'management.badges.needsRequirements', defaultMessage: 'Needs at least one requirement' }, noBadges: { id: 'management.no_badges', defaultMessage: 'There are no badges yet.' }, poi: { id: 'management.badges.poi', defaultMessage: 'Points of Interest' }, remove: { id: 'management.remove', defaultMessage: 'Remove' }, requirements: { id: 'management.badges.requirements', defaultMessage: 'Requirements' }, - save: { id: 'management.button.save', defaultMessage: 'Save' }, uploadNew: { id: 'management.badges.uploadNew', defaultMessage: 'Upload new' }, uploading: { id: 'management.badges.uploading', defaultMessage: 'Uploading...' }, value: { id: 'management.badges.value', defaultMessage: 'Value' }, waterway: { id: 'management.badges.waterway', defaultMessage: 'km of waterways added' }, }); + +// These ids are declared once, in teamsAndOrgs/messages.js. Re-export rather than +// re-declare them: duplicate ids make `yarn build-locales` fail outright. +const messages = { + ...ownMessages, + add: managementMessages.add, + badges: managementMessages.badges, + cancel: managementMessages.cancel, + description: managementMessages.description, + image: managementMessages.image, + manage: managementMessages.manage, + name: managementMessages.name, + save: managementMessages.save, +}; + +export default messages; diff --git a/frontend/src/components/header/messages.js b/frontend/src/components/header/messages.js index 4cb6ad151f..e9694f9cd8 100644 --- a/frontend/src/components/header/messages.js +++ b/frontend/src/components/header/messages.js @@ -179,8 +179,4 @@ export default defineMessages({ id: 'serviceWorker.dialog.remindMeLater', defaultMessage: 'Remind me later', }, - sandbox: { - id: 'project.detail.sandbox', - defaultMessage: 'Sandbox Mode', - }, }); diff --git a/frontend/src/components/levels/messages.js b/frontend/src/components/levels/messages.js index e9a9fcbab2..791ec995ab 100644 --- a/frontend/src/components/levels/messages.js +++ b/frontend/src/components/levels/messages.js @@ -1,17 +1,27 @@ import { defineMessages } from 'react-intl'; -export default defineMessages({ +import managementMessages from '../teamsAndOrgs/messages'; + +const ownMessages = defineMessages({ add: { id: 'management.levels.add', defaultMessage: 'Add' }, approvals_required: { id: 'management.levels.approvals_required', defaultMessage: 'Approvals required' }, - cancel: { id: 'management.button.cancel', defaultMessage: 'Cancel' }, color: { id: 'management.levels.color', defaultMessage: 'Color' }, levelInfoTitle: { id: 'management.titles.level_information', defaultMessage: 'Level information' }, - levels: { id: 'management.levels', defaultMessage: 'Levels' }, - manage: { id: 'management.link.manage', defaultMessage: 'Manage {entity}' }, - name: { id: 'management.fields.name', defaultMessage: 'Name' }, noLevels: { id: 'management.no_levels', defaultMessage: 'There are no levels yet.' }, peer_review: { id: 'management.levels.peer_review', defaultMessage: 'Require peer review' }, required_badges: { id: 'management.levels.required_badges', defaultMessage: 'Required badges' }, - save: { id: 'management.button.save', defaultMessage: 'Save' }, needsBadges: { id: 'management.levels.needsBadges', defaultMessage: 'Needs at least one badge' }, }); + +// These ids are declared once, in teamsAndOrgs/messages.js. Re-export rather than +// re-declare them: duplicate ids make `yarn build-locales` fail outright. +const messages = { + ...ownMessages, + cancel: managementMessages.cancel, + levels: managementMessages.levels, + manage: managementMessages.manage, + name: managementMessages.name, + save: managementMessages.save, +}; + +export default messages; diff --git a/frontend/src/components/projectEdit/messages.js b/frontend/src/components/projectEdit/messages.js index b1c3d0608e..55ac8124e4 100644 --- a/frontend/src/components/projectEdit/messages.js +++ b/frontend/src/components/projectEdit/messages.js @@ -752,15 +752,15 @@ export default defineMessages({ defaultMessage: 'Something went wrong!', }, databse: { - id: 'management.projects.create.review.database', + id: 'management.projects.edit.database', defaultMessage: 'Database', }, databaseOSM: { - id: 'management.projects.create.review.database.osm', + id: 'management.projects.edit.database.osm', defaultMessage: 'OSM', }, databaseSandbox: { - id: 'management.projects.create.review.database.sandbox', + id: 'management.projects.edit.database.sandbox', defaultMessage: 'Sandbox', }, disabledSandboxPriority: { diff --git a/frontend/src/components/taskSelection/messages.js b/frontend/src/components/taskSelection/messages.js index 8867d30625..a60367bde1 100644 --- a/frontend/src/components/taskSelection/messages.js +++ b/frontend/src/components/taskSelection/messages.js @@ -859,7 +859,7 @@ export default defineMessages({ 'You need to be member of one of the mapping teams to be able to map this project.', }, infoBox: { - id: 'project.detail.sandbox', + id: 'project.detail.sandbox.info', defaultMessage: 'Sandbox(Practice)', }, infoBoxTooltip: { From 56bbf33236f7e80089286481046a3529623e4eac Mon Sep 17 00:00:00 2001 From: Sumit Dahal Date: Thu, 20 Aug 2026 13:36:05 +0545 Subject: [PATCH 2/4] chore: regenerate en.json translation source --- frontend/src/locales/en.json | 154 +++++++++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 6 deletions(-) diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 42403406d6..b4a8591c7a 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -1,4 +1,22 @@ { + "management.titles.badge_information": "Badge information", + "management.badges.building": "buildings added", + "management.badges.changeset": "Number of changesets", + "management.badges.changesets": "Changesets", + "management.badges.hidden": "Hide this badge from users", + "management.badges.highway": "km of highways added", + "management.badges.road": "km of roads added", + "management.badges.imageError": "Error uploading image", + "management.badges.metric": "Metric", + "management.badges.needsRequirements": "Needs at least one requirement", + "management.no_badges": "There are no badges yet.", + "management.badges.poi": "Points of Interest", + "management.remove": "Remove", + "management.badges.requirements": "Requirements", + "management.badges.uploadNew": "Upload new", + "management.badges.uploading": "Uploading...", + "management.badges.value": "Value", + "management.badges.waterway": "km of waterways added", "banner.title": "About the information we collect", "banner.button.disagree": "I do not agree", "banner.button.agree": "I agree", @@ -16,6 +34,7 @@ "comment.hashtags.help.managers": "Add \"{hashtag}\" to notify the project managers about your comment.", "comment.hashtags.help.author": "Add \"{hashtag}\" to notify the project author about your comment.", "comment.hashtags.help.contributors": "Add \"{hashtag}\" to notify the task contributors about your comment.", + "comment.hashtags.help.mappers": "Add \"{hashtag}\" to notify the task mappers about your comment.", "comment.preview.nothingToPreview": "Nothing to preview", "comment.preview.leaveAComment": "Leave a comment...", "textarea.write": "Write", @@ -53,12 +72,15 @@ "deleteModal.status.success": "{type} deleted successfully.", "deleteModal.status.success.projects": "Project deleted successfully.", "deleteModal.status.success.teams": "Team deleted successfully.", + "deleteModal.status.success.users": "User deleted successfully.", "deleteModal.status.success.organisations": "Organisation deleted successfully.", "deleteModal.status.success.partners": "Partner deleted successfully.", "deleteModal.status.success.interests": "Interest deleted successfully.", "deleteModal.status.success.licenses": "License deleted successfully.", "deleteModal.status.success.comments": "Comment deleted successfully.", "deleteModal.status.success.campaigns": "Campaign deleted successfully.", + "deleteModal.status.success.badges": "Badge deleted successfully.", + "deleteModal.status.success.levels": "Level deleted successfully.", "deleteModal.status.failure.projects": "An error occurred when trying to delete this project.", "deleteModal.status.failure.organisations": "An error occurred when trying to delete this organization.", "deleteModal.status.failure.partners": "An error occurred when trying to delete this partners.", @@ -67,8 +89,12 @@ "deleteModal.status.failure.campaigns": "An error occurred when trying to delete this campaign.", "deleteModal.status.failure.notifications": "An error occurred when trying to delete this notification.", "deleteModal.status.failure.teams": "An error occurred when trying to delete this team.", + "deleteModal.status.failure.users": "An error occurred when trying to delete this user.", "deleteModal.status.failure.comments": "An error occurred when trying to delete this comment.", + "deleteModal.status.failure.badges": "An error occurred when trying to delete this badge.", + "deleteModal.status.failure.levels": "An error occurred when trying to delete this level.", "deleteModal.button.delete": "Delete", + "deleteModal.button.delete.user": "Yes, Delete Permanently", "deleteModal.status.failure.InternalServerErrorError": "Something has gone wrong on the server, but the server could not be more specific on what the exact problem is.", "deleteModal.status.failure.HasMappedTasksError": "Project has mapped tasks, cannot be deleted.", "deleteModal.button.cancel": "Cancel", @@ -80,8 +106,15 @@ "deleteModal.title.campaigns": "Are you sure you want to delete this campaign?", "deleteModal.title.notifications": "Are you sure you want to delete this notification?", "deleteModal.title.teams": "Are you sure you want to delete this team?", + "deleteModal.title.users": "Are you sure you want to permanently delete this user?", + "deleteModal.description.users": "All user information, history, and associated data will be deleted forever. This action cannot be reversed.", "deleteModal.title.comments": "Are you sure you want to delete this comment?", + "deleteModal.title.badges": "Are you sure you want to delete this badge?", + "deleteModal.title.levels": "Are you sure you want to delete this level?", "deleteModal.error.OrgHasProjectsError": "Organisation has some projects. Please delete them first.", + "deleteModal.error.levelHasUsersError": "Some users have this level so it can't be deleted", + "deleteModal.error.levelBeginner": "You can't delete the beginner level", + "deleteModal.error.badgeHasUsersError": "You can't delete a badge that users have earned", "header.nav.projects": "Explore projects", "header.nav.learn": "Learn", "header.nav.aboutLink": "About", @@ -164,6 +197,14 @@ "home.testimonials.title": "You can make a difference", "home.testimonials.ifrc.citation": "In the early days of the Cyclone Idai response, IFRC was looking for detailed maps to get a sense of the scale of the flooding, which were also used for search and rescue operations. Later on, we had requests to identify where certain buildings, such as health centres or hospitals, were located so our health team could assess the damage and medical needs of patients.", "home.testimonials.ifrc.bio": "Remote Coordinator for the IFRC Information Management Team for Cyclone Idai", + "management.levels.add": "Add", + "management.levels.approvals_required": "Approvals required", + "management.levels.color": "Color", + "management.titles.level_information": "Level information", + "management.no_levels": "There are no levels yet.", + "management.levels.peer_review": "Require peer review", + "management.levels.required_badges": "Required badges", + "management.levels.needsBadges": "Needs at least one badge", "localeSelect.language": "Language", "formInputs.organisation.select": "Select organization", "formInputs.country.select": "Country", @@ -377,6 +418,9 @@ "management.projects.create.arbitrary_tasks": "Set tasks using uploaded polygons", "management.projects.create.draw.description": "Draw the Area of Interest on the map or import a file.", "management.projects.create.upload.description": "The supported file formats are: GeoJSON, KML, OSM or zipped Shapefile. You can drag and drop a file over the map to import it.", + "management.projects.create.review.database": "Where should edits be saved?", + "management.projects.create.review.database.osm": "OpenStreetMap (Live)", + "management.projects.create.review.database.sandbox": "Training Sandbox (Practice)", "project.detail.teams.empty": "This project doesn't have any teams associated with.", "project.detail.coordination": "Coordination", "project.detail.coordination.description": "This project is coordinated by {organisation} and was created by {user}.", @@ -417,7 +461,9 @@ "project.detail.teams_permissions": "Teams & Permissions", "project.detail.author": "Author", "project.detail.mapping_permissions": "Who can map?", + "project.detail.mapping_permissions_level": "Minimum mapper level", "project.detail.validation_permissions": "Who can validate?", + "project.detail.validation_permission_level": "Minimum validator level", "project.detail.zoomToTasks": "Zoom to tasks", "project.detail.cards.selectATask.title": "1. Select a task", "project.detail.cards.mapthroughosm.title": "2. Map with OpenStreetMap", @@ -460,6 +506,9 @@ "project.inaccessible.exploreOtherProjects": "Explore other projects", "project.noSimilarProjectsFound": "Could not find any similar projects for this project", "project.viewProjectSpecificInstructions": "View project specific instructions", + "project.permissions.having": "having", + "project.permissions.levelOrAbove": "level or above", + "project.detail.sandbox": "Sandbox Mode", "projects.formInputs.privacy.title": "Privacy", "projects.formInputs.privacy.field": "Private project", "projects.formInputs.privacy.description": "Private means that only the users that are project team members can access, map or validate this project. This option overrides the mapping and validation permissions.", @@ -475,11 +524,11 @@ "projects.formInputs.organisation.select": "Select organization", "projects.formInputs.campaign.select": "Select campaigns", "projects.formInputs.permissions.any": "Any user", - "projects.formInputs.permissions.level": "Only users with intermediate or advanced level", "projects.formInputs.permissions.teams": "Only team members", - "projects.formInputs.permissions.teamsAndLevel": "Only intermediate and advanced team members", "projects.formInputs.permissions.mapping.description": "Define which users can map this project.", + "projects.formInputs.permissions.mapping.levelDescription": "Choose a minimum level required to map this project.", "projects.formInputs.permissions.validation.description": "Define which users can validate this project.", + "projects.formInputs.permissions.validation.levelDescription": "Choose a minimum level required to validate this project.", "projects.formInputs.permissions.mapping.title": "Mapping permissions", "projects.formInputs.permissions.validation.title": "Validation permissions", "projects.sections.mapping_validation.title": "Mapping, validation and invalidation", @@ -639,8 +688,16 @@ "projects.partner.actions.link.success.toast": "Successfully linked the partner.", "projects.partner.listing.empty": "No partners are associated with this project yet.", "projects.partner.listing.error": "Something went wrong!", + "management.projects.edit.database": "Database", + "management.projects.edit.database.osm": "OSM", + "management.projects.edit.database.sandbox": "Sandbox", + "projects.formInputs.priority.disabled_sandbox": "Priority cannot be changed for sandbox projects.", "project.mainSection.title": "Generic project", "project.nav.mappingDifficulty": "Difficulty level", + "project.nav.mappingDatabase": "Mapping Mode", + "project.nav.mappingDatabase.option.all": "All", + "project.nav.mappingDatabase.option.sandbox": "Sandbox (No real OSM edits)", + "project.nav.mappingDatabase.option.OSM": "OpenStreetMap (Live)", "project.nav.moreFilters": "More filters", "project.nav.campaign": "Campaign", "navFilters.startDate": "From", @@ -702,6 +759,8 @@ "project.nav.apply": "Apply", "project.nav.clear": "Clear", "project.results.retry": "Retry", + "project.navFilters.imagery": "Imagery", + "project.navFilters.selectImagery": "Select imagery", "project.navFilters.partner": "Partner", "project.navFilters.partnerDates": "Partner Dates", "project.navFilters.partnerFromDate": "Date From", @@ -866,6 +925,11 @@ "project.tasks.action.resources": "Resources", "project.tasks.action.finish_mapping.title": "Once you have finished mapping", "project.tasks.action.instructions.select_task": "Select one of the options below that matches your edit status", + "project.tasks.tab.instructions.description": "Read the task guidelines and mapping steps before you begin.", + "project.tasks.tab.history.description": "View past mapping and validation activity, including comments.", + "project.tasks.tab.completion.description": "Leave comments, unlock the task, and update its status.", + "project.tasks.tab.resources.description": "Access reference materials, links, and supporting data.", + "project.tasks.tab.heading": "Other tabs", "project.input.placeholder.write_comment": "Write a comment", "project.tasks.action.instructions.leave_comment": "Leave a comment (optional)", "project.tasks.action.instructions.submit_task": "Submit your work", @@ -883,7 +947,9 @@ "project.tasks.action.options.mapped_question": "Is this task completely mapped?", "project.tasks.action.options.validated_question": "{number, plural, one {Is this task well mapped?} other {Are these tasks well mapped?}}", "project.tasks.action.options.complete": "Yes", + "project.tasks.action.options.valid_mapping": "Task well mapped, thanks for mapping", "project.tasks.action.options.incomplete": "No", + "project.tasks.action.options.invalid_mapping": "More work is required to complete this task. Please carefully read the comment section for further information.", "project.tasks.action.options.bad_imagery": "The imagery is bad", "project.tasks.action.split_task": "Split task", "project.tasks.action.split_task.error": "It was not possible to split the task", @@ -948,6 +1014,31 @@ "project.permissions.error.userLevelToMap": "Only users with intermediate or advanced experience level can map this project.", "project.permissions.error.userIsNotValidationTeamMember": "You need to be member of one of the validation teams to be able to validate this project.", "project.permissions.error.userIsNotMappingTeamMember": "You need to be member of one of the mapping teams to be able to map this project.", + "project.detail.sandbox.info": "Sandbox(Practice)", + "project.detail.sandbox.tooltip": "This is a training project. Edits will not be saved to OpenStreetMap.", + "project.tasks.osm_data_controls.title": "OSM Data Controls", + "project.tasks.osm_data_controls.opacity.description": "Adjust OSM data layer opacity", + "project.tasks.osm_data_controls.opacity.hidden": "0% (Hidden)", + "project.tasks.osm_data_controls.opacity.solid": "100% (Solid)", + "project.tasks.osm_data_controls.fetching": "Fetching OSM features...", + "project.tasks.osm_data_controls.error.title": "Error Loading Features", + "project.tasks.osm_data_controls.error.description": "Failed to fetch OSM features for this task.", + "project.tasks.osm_data_controls.reset": "Reset", + "project.tasks.osm_data_controls.layer.title": "OSM Features Layer", + "project.tasks.osm_data_controls.layer.description.initial": "Load and display existing OpenStreetMap features.", + "project.tasks.osm_data_controls.layer.description.ready": "OSM features are loaded and ready.", + "project.tasks.osm_data_controls.load.button": "Load OSM Features", + "project.tasks.osm_data_controls.show.button": "Show OSM Features", + "project.tasks.osm_data_controls.hide.title": "Hide OSM features", + "project.tasks.osm_data_controls.show.title": "Show OSM features", + "project.tasks.map.invalidationChoropleth": "Legend", + "project.tasks.map.invalidationChoropleth.toggle": "Show invalidation heatmap", + "project.tasks.map.invalidationChoropleth.legend.title": "Invalidation count", + "project.tasks.map.invalidationChoropleth.legend.none": "Never invalidated", + "project.tasks.map.invalidationChoropleth.legend.low": "1–2 times", + "project.tasks.map.invalidationChoropleth.legend.medium": "3–5 times", + "project.tasks.map.invalidationChoropleth.legend.high": "6+ times", + "project.tasks.map.invalidationChoropleth.legend.rampHint": "Colour blends continuously between stops", "management.messages.notAllowed": "You are not allowed to manage organizations.", "management.messages.imageUpload.error": "The image upload failed.", "management.fields.managers": "Managers", @@ -958,6 +1049,8 @@ "management.link.manage": "Manage {entity}", "management.link.edit.team": "Edit team", "management.partners.menu": "Partners", + "management.badges": "Badges", + "management.levels": "Levels", "management.edit.resourcesButton": "Resources link", "management.members.edit": "Edit", "management.members.alreadyInTeam": "Already in team", @@ -969,6 +1062,7 @@ "management.teams.validation": "Validation teams", "management.teams.members": "Team members", "management.teams.members.send_message": "Team messaging", + "management.campaigns.contributors.send_message": "Message contributors", "management.teams.members.send_message.success": "Message sent", "management.teams.members.send_message.failure": "Failed to send message. Please try again.", "management.teams.members.send_message.button": "Send", @@ -1096,7 +1190,16 @@ "management.stats.title": "Statistics", "management.stats.overview": "Overview", "management.stats.features": "Total features", - "user.nextLevel": "{changesets} / {nextLevelThreshold} changesets to {level}", + "management.members.remove_confirmation_header": "Are you sure you want to remove?", + "management.members.remove_confirmation_description": "This team will have only managers and no members.", + "management.teams.project.view": "View", + "management.teams.project.unlink": "Unlink", + "management.teams.project.unlink_all": "Unlink All", + "management.teams.project.unlink_selected": "Unlink Selected", + "management.teams.project.unlink.confirmation_dialog_header": "Are You sure you want to unlink projects?", + "management.teams.project.unlink.confirmation_dialog_body": "Once the unlinking project is successful you cannot undo this operation.", + "management.teams.project.unlink.selected": "selected", + "user.nextLevel": "{changesets} / {nextLevelThreshold} {metric} to level {level}", "user.personalInfo": "Personal information", "user.name": "Name", "user.organisations": "Organizations", @@ -1130,10 +1233,12 @@ "user.notifications.teams": "Team announcements emails", "user.notifications.teams.description": "Receive emails with announcements sent by team managers.", "user.notifications.projects": "Project updates", - "user.notifications.tasks": "Tasks validation emails", + "user.notifications.tasks.validation": "Task validation emails", + "user.notifications.tasks.invalidation": "Task invalidation emails", "user.settings.required": "Required fields", "user.notifications.projects.description": "You get a notification when a project you have contributed to makes progress.", - "user.notifications.task.description": "Receive an email when a task you have contributed to is validated.", + "user.notifications.task.validation.description": "Receive an email when a task you have contributed to is validated.", + "user.notifications.task.invalidation.description": "Receive an email when a task you have contributed to is invalidated.", "user.notifications.questionsAndComments": "Questions and comments", "user.notifications.questionsAndComments.description": "Receive a notification every time someone posts in the 'Questions and comments' section of the projects you have contributed to or created.", "user.notifications.taskComments": "Task comments", @@ -1176,6 +1281,7 @@ "users.list.total": "Total number of users: {total}", "users.list.actions.setRole": "Set role", "users.list.actions.setLevel": "Set mapper level", + "users.list.actions.redact": "Redact user information", "users.list.attribute.updation.success": "User {attribute, select, role {role} mapperLevel {mapper level} other {attribute}} updated", "users.list.attribute.updation.failure": "Failed to update user {attribute, select, role {role} mapperLevel {mapper level} other {attribute}}. Please try again.", "user.mapper_level.options.all": "All levels", @@ -1186,7 +1292,33 @@ "user.user_role.options.admin": "Admin", "user.user_role.options.read_only": "Blocked", "user.user_role.options.mapper": "Mapper", + "user.user_role.options.delete": "Delete User", "user.nav.clearFilters": "Clear filters", + "user.table.failedUdatingStats": "Failed updating stats", + "user.table.never": "Never", + "user.table.statsUpdated": "Stats updated", + "user.table.actions": "Actions", + "user.table.lastUpdated": "Last updated", + "user.table.level": "Mapper level", + "user.table.role": "Role", + "user.table.upgrade": "Level upgrade", + "user.table.username": "Username", + "user.table.highway": "Highways", + "user.table.road": "Roads", + "user.table.waterway": "Waterways", + "user.table.building": "Buildings", + "user.table.changeset": "Changesets", + "user.table.poi": "PoI", + "user.table.approve": "Approve", + "user.levelApproved": "User approved", + "user.failedApprovingLevel": "Failed approving level", + "user.alreadyVoted": "You already voted", + "user.progress.changeset": "changesets", + "user.progress.waterway": "km of waterways", + "user.progress.highway": "km of highways", + "user.progress.road": "km of roads", + "user.progress.poi": "points of interest", + "user.progress.building": "buildings", "users.detail.loading": "loading", "users.detail.contributionTimelineTitle": "Contribution Timeline", "users.detail.projectsTitle": "Projects", @@ -1218,6 +1350,7 @@ "users.detail.heatmapLegendLess": "less", "users.detail.teams": "Teams", "users.header.organisations.error": "Couldn't load organisations at this time", + "users.header.achievements": "Achievements", "error.page.title": "An error occurred", "error.page.description": "Something did not work well...", "error.page.link": "Return", @@ -1282,11 +1415,19 @@ "teamsAndOrgs.management.titles.campaign_information": "Campaign information", "management.license.manage": "Manage license", "management.category.manage": "Manage category", + "management.badge.manage": "Manage badge", + "management.level.manage": "Manage level", "management.interest.title": "Category information", "management.license.title": "License information", + "management.badge.title": "Badge information", + "management.level.title": "Level information", "management.category.creation": "Create new category", "management.license.creation": "Create new license", + "management.badge.creation": "Create new badge", + "management.level.creation": "Create new level", "management.license.button.create": "Create license", + "management.badge.button.create": "Create badge", + "management.level.button.create": "Create level", "management.category.button.create": "Create category", "taskAction.messages.error.no_locked_tasks.text": "You don't have any locked tasks. Access the Project #{currentProject} to select a task to map.", "taskAction.go_to_project.button": "Go to Project #{project}", @@ -1396,6 +1537,7 @@ "pages.edit_project.actions.missing_fields": "{number, plural, one {One required field is missing:} other {Some required fields are missing:}}", "pages.edit_project.actions.missing_fields_for_locale": "Missing information in the project's default language ({locale}):", "pages.edit_project.actions.missing_fields_for_teams": "{mapping, select, true {Mapping} other {{validation, select, true {Validation} other {}}}} {mapping, select, true {{validation, select, true {and validation} other {}}} other {}} permissions have been set only to team members but no team has been added.", + "pages.edit_project.actions.duplicate_teams_assigned": "Same team assigned multiple times for same role", "pages.edit_project.sections.description": "Description", "pages.edit_project.sections.instructions": "Instructions", "pages.edit_project.sections.metadata": "Metadata", @@ -1411,4 +1553,4 @@ "management.partner.stats.mapswipe.info": "It may take up to 48 hours for updates", "management.partners.stats.mapswipe.swipes": "Swipes", "management.partners.stats.mapswipe.page.error": "Something went wrong! Could not load data." -} +} \ No newline at end of file From 2108b51191aeeceb0b4548c3a184e038f810977b Mon Sep 17 00:00:00 2001 From: Sumit Dahal Date: Thu, 20 Aug 2026 13:37:12 +0545 Subject: [PATCH 3/4] ci: fail PRs on duplicate or stale translation message ids --- .github/workflows/pr_test_frontend.yml | 11 +++++++++++ docs/developers/translations.md | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr_test_frontend.yml b/.github/workflows/pr_test_frontend.yml index 89298ab5e5..c1c480b053 100644 --- a/.github/workflows/pr_test_frontend.yml +++ b/.github/workflows/pr_test_frontend.yml @@ -56,6 +56,17 @@ jobs: working-directory: ./frontend run: yarn install + # Fails on a duplicate message id (build-locales exits non-zero) and on a + # stale catalog (regenerating changes the committed file). See #7284. + - name: Check translation source file is up to date + working-directory: ./frontend + run: | + yarn build-locales + # combine-messages writes no trailing newline; pre-commit's end-of-file-fixer + # adds one to the committed file. Match it so the diff is content-only. + [ -z "$(tail -c1 src/locales/en.json)" ] || printf '\n' >> src/locales/en.json + git diff --exit-code -- src/locales/en.json + - name: Run Yarn test working-directory: ./frontend run: yarn test diff --git a/docs/developers/translations.md b/docs/developers/translations.md index 9d42511214..f92162cf6c 100644 --- a/docs/developers/translations.md +++ b/docs/developers/translations.md @@ -77,9 +77,10 @@ If you run into certificate-related errors, update the paths in the script or tr - `yarn build-locales` - Execute that command in the `frontend` folder to get the new translatable strings from all the `messages.js` files in the frontend code. The changes in the strings - will be pushed to `frontend/src/locales/en.json` file. The ideal is - to execute that command before every pull request that change - something in the translatable strings. + will be pushed to `frontend/src/locales/en.json` file. Run it before + opening any pull request that changes translatable strings: CI + regenerates the file and fails the build if the committed copy is + stale, or if two `messages.js` files declare the same message id. - After the pull request is merged to the `develop` branch, the command `tx push -s` needs to be executed in order to push the changes to Transifex. The translators receive a notification every From bcb9a0c120ed40d4d12696394d21ba183d049c56 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 20 Aug 2026 08:51:28 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- frontend/src/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index b4a8591c7a..4d0b4c02a0 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -1553,4 +1553,4 @@ "management.partner.stats.mapswipe.info": "It may take up to 48 hours for updates", "management.partners.stats.mapswipe.swipes": "Swipes", "management.partners.stats.mapswipe.page.error": "Something went wrong! Could not load data." -} \ No newline at end of file +}