Gitfed
bastien-mrq/gitfed / internal / i18n / strings_en.go
package i18n

var en = map[string]string{
	// ---------- nav / shell ----------
	"nav.home":                 "Home",
	"nav.explore":              "Explore",
	"nav.security":             "Security",
	"nav.dashboard":            "My repos",
	"nav.search_placeholder":   "Search repos…",
	"nav.login":                "Log in",
	"nav.signed_in_as":         "Signed in as",
	"nav.settings":             "Settings",
	"nav.admin":                "Admin",
	"nav.logout":               "Log out",
	"nav.notifications":        "Notifications",
	"theme.system":             "Auto",
	"theme.light":              "Light",
	"theme.dark":               "Dark",
	"theme.toggle":             "Toggle theme",
	"settings.tab_preferences": "Preferences",
	"settings.theme_title":     "Theme",
	"settings.theme_hint":      "Auto follows your system's setting. This also sets the small toggle in the nav.",
	"footer.changelog":         "Gitfed %s",

	// ---------- explore ----------
	"explore.title":              "Explore public repositories",
	"explore.subtitle":           "Public repos on this instance, readable by anyone — clonable over HTTPS with no account.",
	"explore.repo_count":         "public repos",
	"explore.search_placeholder": "Filter by name…",
	"explore.topics_label":       "Topics",
	"explore.clear":              "clear",
	"explore.col_repo":           "Repo",
	"explore.col_owner":          "Owner",
	"explore.col_topics":         "Topics",
	"explore.empty_title":        "No public repositories match",
	"explore.empty_hint":         "Try a different topic or search, or clear the filter.",

	// ---------- profile ----------
	"profile.joined":         "Joined",
	"profile.keys_title":     "Public keys",
	"profile.keys_hint":      "SHA256 fingerprints only — never the full key.",
	"profile.repos_title":    "Public repositories",
	"profile.no_repos":       "No public repositories yet.",
	"profile.activity_title": "Recent activity",
	"profile.no_activity":    "No recent activity.",

	// ---------- landing ----------
	"landing.title":               "",
	"landing.kicker":              "self-hosted & federated git",
	"landing.h1_1":                "Your code. Your server.",
	"landing.h1_2":                "Your rules.",
	"landing.lead":                "Gitfed is a git server you run yourself — so you keep ownership of your code and your data, without giving up the ability to collaborate with anyone, wherever they host their own instance.",
	"landing.cta_explore":         "Explore public repos",
	"landing.cta_security":        "How it's secured →",
	"landing.pillar1_h":           "Ownership",
	"landing.pillar1_p":           "Your code and your data stay on your machine, your server, your infrastructure. No third-party platform can mine it, shut it down, or cut off your access.",
	"landing.pillar2_h":           "Federation",
	"landing.pillar2_p":           "Each instance stays independent, but can trust others — a bit like email. One account, on your own instance, is enough to push code to an instance that trusts you.",
	"landing.pillar3_h":           "Control",
	"landing.pillar3_p":           "Public or private, read or write, per repo, per person. You decide — no platform-wide policy gets imposed on you.",
	"landing.split_h":             "One account at home, not one everywhere",
	"landing.split_p":             "When someone from another instance wants to collaborate on one of your repos, they don't create an account with you: their home instance signs a certificate proving who they are, and your instance checks that it trusts that instance. Once trust is established, everything happens locally — no network call on every `git push`.",
	"landing.split_link_security": "More on security",
	"landing.split_link_explore":  "Explore repos",
	"landing.diagram_you":         "Your instance",
	"landing.diagram_friend":      "A friend's instance",
	"landing.diagram_cert":        "certificate",
	"landing.diagram_trust":       "trust verified",
	"landing.diagram_no_account1": "no \"bob\" account",
	"landing.diagram_no_account2": "on alice's instance",
	"landing.cta_band_h":          "Ready to take back control of your code?",
	"landing.cta_band_p":          "Gitfed is open-source and self-hosted — one Go binary, one embedded database, no external dependencies.",
	"landing.cta_band_dashboard":  "Go to your repos",
	"landing.changelog_link":      "Full changelog",

	// ---------- security ----------
	"security.title":  "Security",
	"security.kicker": "security model",
	"security.h1":     "Why it's secure, explained simply",
	"security.lead":   "No unnecessary jargon: here's, step by step, how Gitfed protects your code — from transport to your collaborators' identity.",

	"security.s1_tag":            "01 · transport",
	"security.s1_h":              "SSH only, never git over HTTP",
	"security.s1_p":              "Gitfed exposes no git-over-HTTP protocol. Every read or write goes over SSH — a protocol proven for 25 years, with a single door to watch instead of two.",
	"security.s1_diagram_client": "git clone/push",
	"security.s1_diagram_open":   "SSH — open",
	"security.s1_diagram_http":   "HTTP git — doesn't exist",
	"security.s1_diagram_repos":  "repos",
	"security.s1_caption":        "A single network entry point for git: the SSH port.",

	"security.s2_tag":                    "02 · identity",
	"security.s2_h":                      "Short-lived certificates, not shared passwords",
	"security.s2_p":                      "Every instance generates its own certificate authority. Your instance signs a certificate proving who you are, valid for 24h by default — never a long-lived secret that can leak.",
	"security.s2_diagram_haskey":         "has an SSH key",
	"security.s2_diagram_step1":          "1. requests",
	"security.s2_diagram_alice_instance": "alice's instance",
	"security.s2_diagram_local_ca":       "local authority (CA)",
	"security.s2_diagram_signs":          "signs 24h",
	"security.s2_diagram_step2":          "2. certificate",
	"security.s2_diagram_bob_instance":   "bob's instance",
	"security.s2_diagram_trust1":         "does it trust",
	"security.s2_diagram_trust2":         "this CA?",
	"security.s2_diagram_access":         "access",
	"security.s2_diagram_local1":         "verification is 100% local from here —",
	"security.s2_diagram_local2":         "no network call on every push",
	"security.s2_caption":                "alice asks her own instance for a certificate, presents it to bob's, which checks its trust in alice's instance.",

	"security.s3_tag":                   "03 · trust",
	"security.s3_h":                     "Trust between instances is explicit, never automatic",
	"security.s3_p":                     "The first time an unknown instance shows up, Gitfed reads its public profile (/.well-known/gitfed.json) then puts its key on hold — an admin has to approve it before any access is granted. Discovery is also capped at 10 new domains per minute, to prevent abuse.",
	"security.s3_diagram_unknown":       "Unknown domain",
	"security.s3_diagram_unknown_sub":   "contacts your instance",
	"security.s3_diagram_discovery":     "Discovery",
	"security.s3_diagram_discovery_sub": "reads its public CA key",
	"security.s3_diagram_pending":       "Pending",
	"security.s3_diagram_pending_sub":   "until an admin acts",
	"security.s3_diagram_approved":      "Approved",
	"security.s3_diagram_approved_sub":  "an admin's decision",

	"security.s4_tag":     "04 · isolation",
	"security.s4_h":       "Web access and git access share nothing",
	"security.s4_p":       "The web UI password has nothing to do with your git access: it's hashed (bcrypt), never stored in clear text, and only opens an opaque, time-limited web session. A `git push` never depends on this password — only on your SSH key or certificate.",
	"security.s4_fact1_h": "Precise per-repo roles",
	"security.s4_fact1_p": "read, write, admin — never all-or-nothing.",
	"security.s4_fact2_h": "Public ≠ writable",
	"security.s4_fact2_p": "a public repo opens for reading, never for writing without an explicit grant.",
	"security.s4_fact3_h": "Session cookies",
	"security.s4_fact3_p": "HttpOnly, Secure, SameSite — unreachable from JavaScript.",
	"security.s4_fact4_h": "Audit log",
	"security.s4_fact4_p": "every access decision, allowed or denied, is recorded.",

	// ---------- common ----------
	"common.public":  "public",
	"common.private": "private",
	"role.owner":     "owner",
	"role.read":      "read",
	"role.write":     "write",
	"role.admin":     "admin",

	// ---------- dashboard ----------
	"dashboard.title":                   "Your repos",
	"dashboard.stat_repos":              "Repos",
	"dashboard.stat_public":             "Public",
	"dashboard.stat_shared":             "Shared with you",
	"dashboard.add_repo":                "Add a repo",
	"dashboard.new_repo":                "New repo",
	"dashboard.repo_name":               "Name",
	"dashboard.create":                  "Create",
	"dashboard.empty":                   "No repos yet — create one above.",
	"dashboard.msg_created":             "created %s",
	"dashboard.msg_name_required":       "repository name is required",
	"dashboard.msg_bad_namespace":       "you can only create repositories in your own namespace",
	"dashboard.msg_quota":               "you have reached the maximum number of repositories",
	"dashboard.import_repo":             "Import from URL",
	"dashboard.import_url_label":        "Source repository URL (HTTPS)",
	"dashboard.import":                  "Import",
	"dashboard.msg_import_url_required": "source repository URL is required",
	"dashboard.msg_imported":            "imported %s",

	// ---------- pinned repos ----------
	"dashboard.pinned_title":    "Pinned elsewhere",
	"dashboard.pinned_note":     "Bookmarks to repos on other instances — a link, not a credential. Works for public repos with no login; a private one just needs a session on that instance.",
	"dashboard.pin_add":         "Pin a repo",
	"dashboard.pin_input_label": "Repo URL or domain/owner/repo",
	"dashboard.pin_remove":      "Remove",
	"dashboard.pins_empty":      "Nothing pinned yet.",
	"dashboard.msg_pin_invalid": "couldn't make sense of that as a domain and repo",
	"dashboard.msg_pin_quota":   "you've hit the maximum number of pins",
	"dashboard.msg_pinned":      "pinned %s",

	// ---------- notifications ----------
	"notif.title":            "Notifications",
	"notif.note":             "Another instance telling you that you were granted access somewhere — informational only, and its content isn't independently verified (only that it really was signed by that instance). Accepting just pins the link; it grants nothing by itself, and your actual access is whatever that instance's owner set it to, regardless of what a notification claims.",
	"notif.granted_by":       "granted by",
	"notif.accept":           "Accept",
	"notif.dismiss":          "Dismiss",
	"notif.status_accepted":  "accepted",
	"notif.status_dismissed": "dismissed",
	"notif.empty":            "No notifications.",
	"notif.msg_accepted":     "pinned to My repos",
	"notif.mr_opened":        "%s opened merge request #%d: %s",
	"notif.mr_comment":       "%s commented on merge request #%d: %s",
	"notif.view":             "View",
	"notif.msg_seen":         "marked as seen",

	// ---------- settings ----------
	"settings.title":                "Settings",
	"settings.tab_profile":          "Profile",
	"settings.tab_keys":             "SSH keys",
	"settings.tab_password":         "Password",
	"settings.logged_in_as":         "Logged in as",
	"settings.profile_note":         "This password only signs you into the web UI. Git push/pull always goes over SSH with a key, independently of it.",
	"settings.remove":               "Remove",
	"settings.confirm_remove_key":   "Remove this key? If it's your only one, you'll lose SSH/git access until you add another.",
	"settings.no_keys":              "No keys yet.",
	"settings.add_key":              "Add SSH key",
	"settings.pubkey_label":         "Public key (authorized_keys format)",
	"settings.add":                  "Add",
	"settings.change_password":      "Change password",
	"settings.current_password":     "Current password",
	"settings.new_password":         "New password",
	"settings.msg_key_added":        "key added",
	"settings.msg_key_removed":      "key removed",
	"settings.msg_wrong_password":   "current password is incorrect",
	"settings.msg_password_changed": "password changed",
	"settings.bio_title":            "Public bio",
	"settings.bio_label":            "Shown on your public profile page — Markdown supported.",
	"settings.bio_placeholder":      "A few words about you or what you work on…",
	"settings.public_profile_hint":  "Anyone can view your public profile, even without an account.",
	"settings.view_public_profile":  "View public profile",
	"settings.msg_bio_saved":        "bio saved",
	"settings.msg_bio_too_long":     "bio is too long",

	// ---------- auth ----------
	"auth.login":          "Log in",
	"auth.username":       "Username",
	"auth.password":       "Password",
	"auth.note":           "Accounts are created by an instance admin — there's no self-registration. This only logs you into the web UI; git push/pull still goes over SSH with your key.",
	"auth.invalid_login":  "invalid username or password",
	"auth.rate_limited":   "too many login attempts, try again in a few minutes",
	"auth.error":          "unable to log you in right now, try again later",
	"common.server_error": "an internal error occurred",

	// ---------- search / changelog ----------
	"search.title":      "Search",
	"search.no_matches": "No matches.",
	"search.prompt":     "Type something to search.",
	"changelog.title":   "Changelog",

	// ---------- admin ----------
	"admin.title":                 "Admin",
	"admin.card_users":            "Users",
	"admin.card_users_sub":        "%d admin(s), %d regular",
	"admin.card_users_link":       "Manage users",
	"admin.card_trust":            "Trust store",
	"admin.card_trust_pending":    "pending",
	"admin.card_trust_sub":        "federated domains known",
	"admin.card_trust_link":       "Review trust store",
	"admin.pending_trust_tooltip": "A federated domain is waiting for trust approval — collaborators from it can't authenticate until you review it",
	"admin.card_audit":            "Audit log",
	"admin.card_audit_sub":        "most recent events on record",
	"admin.card_audit_link":       "View audit log",
	"admin.card_repos":            "Storage",
	"admin.card_repos_sub":        "across %d repos",
	"admin.card_repos_link":       "View repos",
	"admin.recent_activity":       "Recent activity",
	"admin.audit_allow":           "allow",
	"admin.audit_deny":            "deny",

	"admin.users_title":         "Admin — Users",
	"admin.users_col_username":  "Username",
	"admin.users_col_keys":      "Keys",
	"admin.revoke_admin":        "Revoke admin",
	"admin.make_admin":          "Make admin",
	"admin.confirm_delete_user": "Delete user",
	"admin.users_empty":         "No users yet.",
	"admin.add_user":            "Add user",
	"admin.initial_password":    "Initial password",
	"admin.grant_admin":         "Grant admin",
	"admin.msg_user_created":    "created user %s",
	"admin.msg_user_deleted":    "deleted user %s",
	"admin.msg_user_updated":    "updated %s",

	"admin.trust_title":          "Admin — Trust store",
	"admin.trust_col_domain":     "Domain",
	"admin.trust_col_status":     "Status",
	"admin.trust_col_first_seen": "First seen",
	"admin.trust_status_pending": "pending",
	"admin.trust_status_trusted": "trusted",
	"admin.approve":              "Approve",
	"admin.trust_empty":          "No remote domains discovered yet.",
	"admin.trust_note":           "Domains show up here automatically the first time a collaborator on a remote domain is granted access to a repo. Under the default whitelist policy they stay pending until approved here.",
	"admin.msg_domain_approved":  "approved %s",

	"admin.audit_title":           "Admin — Audit log",
	"admin.audit_col_time":        "Time",
	"admin.audit_col_action":      "Action",
	"admin.audit_col_principal":   "Principal",
	"admin.audit_col_repo_domain": "Repo/Domain",
	"admin.audit_col_result":      "Result",
	"admin.audit_col_detail":      "Detail",
	"admin.audit_empty":           "No events recorded yet.",
	"admin.audit_note":            "Showing the most recent 200 events.",

	"admin.repos_title":          "Admin — Repos",
	"admin.repos_sub":            "%d repos, %s total on disk",
	"admin.repos_col_name":       "Name",
	"admin.repos_col_owner":      "Owner",
	"admin.repos_col_visibility": "Visibility",
	"admin.repos_col_size":       "Size",
	"admin.repos_empty":          "No repos yet.",

	// ---------- repo ----------
	"repo.owner":                     "owner",
	"repo.copy_clone_url":            "Copy clone URL",
	"repo.read_only":                 "read-only",
	"repo.https_readonly_hint":       "Anonymous clone/fetch only — pushing over HTTPS is never possible, even for a public repo. Push always goes over SSH.",
	"repo.empty":                     "This repository is empty.",
	"repo.directory":                 "directory",
	"repo.file":                      "file",
	"repo.nothing_here":              "Nothing here.",
	"repo.tags":                      "Tags",
	"repo.download":                  "Download",
	"repo.stat_commits":              "%d commits",
	"repo.stat_contributors":         "%d contributors",
	"repo.commits_title":             "Commits",
	"repo.commits_empty":             "No commits yet.",
	"repo.pager_prev":                "Previous",
	"repo.pager_next":                "Next",
	"repo.pager_page":                "Page %d",
	"repo.commit_label":              "commit",
	"repo.parent_label":              "parent",
	"repo.files_changed":             "files changed",
	"repo.diff_truncated":            "This commit's diff is too large to show in full — the list above still shows every changed file.",
	"repo.license":                   "License",
	"repo.view_file":                 "View file",
	"repo.binary_file":               "Binary file — not shown.",
	"repo.settings_title":            "settings",
	"repo.visibility_topics":         "Visibility & topics",
	"repo.public_desc":               "Public (readable by any authenticated principal)",
	"repo.topics_label":              "Topics (comma-separated)",
	"repo.description_label":         "Description",
	"repo.description_placeholder":   "What is this repo for?",
	"repo.save":                      "Save",
	"repo.col_principal":             "Principal",
	"repo.col_role":                  "Role",
	"repo.revoke":                    "Revoke",
	"repo.grant_collaborator":        "Grant collaborator",
	"repo.grant":                     "Grant",
	"repo.grant_note":                "Granting a collaborator on a domain not yet known to this instance triggers federation discovery of that domain's CA — an instance admin needs to approve it under Admin → Trust store (whitelist policy).",
	"repo.confirm_delete":            "Delete",
	"repo.confirm_revoke":            "Revoke access for",
	"repo.danger_zone":               "Danger zone",
	"repo.danger_zone_note":          "Deleting removes the repo's record from Gitfed — it does not delete the bare repo on disk.",
	"repo.collaborators_title":       "Collaborators",
	"repo.federated_collaborator":    "federated collaborator",
	"repo.local_collaborator":        "local collaborator",
	"repo.delete_record":             "Delete repo record",
	"repo.msg_saved":                 "saved settings",
	"repo.msg_granted":               "granted %s %s",
	"repo.msg_granted_pending_trust": "granted %s — but %s is pending trust approval in Admin → Trust store, so they can't authenticate until you approve it",
	"repo.msg_revoked":               "revoked %s",
	"repo.msg_deleted":               "deleted %s",

	// ---------- merge requests ----------
	"mr.list_title":          "Merge requests",
	"mr.new":                 "New merge request",
	"mr.by":                  "opened by",
	"mr.opened_by":           "Opened by",
	"mr.empty_title":         "No merge requests yet",
	"mr.empty_hint":          "Open one to propose merging one branch into another.",
	"mr.need_two_branches":   "This repo needs at least two branches to open a merge request.",
	"mr.branches_label":      "Branches",
	"mr.title_label":         "Title",
	"mr.description_label":   "Description (optional)",
	"mr.cancel":              "Cancel",
	"mr.open":                "Open merge request",
	"mr.status_open":         "open",
	"mr.status_merged":       "merged",
	"mr.status_closed":       "closed",
	"mr.branch_missing":      "One of this merge request's branches no longer exists.",
	"mr.clean_title":         "No conflicts — ready to merge",
	"mr.conflict_title":      "Conflict — can't merge yet",
	"mr.merge":               "Merge",
	"mr.close":               "Close",
	"mr.merged_note":         "Merged by",
	"mr.closed_note":         "Closed without merging.",
	"mr.comment_placeholder": "Add a comment…",
	"mr.comment_submit":      "Comment",
	"mr.msg_invalid":         "pick a title and two different branches",
	"mr.msg_created":         "opened merge request",
	"mr.msg_merged":          "merged",
	"mr.msg_conflict":        "can't merge: conflicting files — resolve locally and push, then try again",
	"mr.msg_closed":          "closed",
	"mr.msg_comment_empty":   "comment can't be empty",
	"mr.msg_commented":       "comment added",
}