//! Strings for the organization pages (`/org/...`), org creation, and the org-related parts of the //! profile, explore and dashboard pages. use super::Lang; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum K { // One-shot notices shown after a redirect (see `pages::org_ctx::NOTICES`). NoticeSettingsSaved, NoticeMemberAdded, NoticeRoleUpdated, NoticeMemberRemoved, NoticeTeamCreated, NoticeTeamSaved, NoticeTeamDeleted, NoticeTeamMemberAdded, NoticeTeamMemberRemoved, NoticeTeamRepoAdded, NoticeTeamRepoRemoved, NoticeEmptyUsername, NoticeUnknownUser, NoticeAlreadyMember, NoticeNotMember, NoticeLastOwner, NoticeInvalidRole, NoticeInvalidName, NoticeTeamDescriptionLength, NoticeTeamExists, NoticeAlreadyInTeam, NoticeNotInOrg, NoticeNotOwned, NoticeAlreadyLinked, NoticeHasRepos, NoticeConfirmName, NoticeDescriptionLength, // Shared labels. Save, Remove, Username, Name, Explore, NewRepository, // Organization creation. NewOrganization, NewOrgIntro, OrgName, DescriptionOptional, CreateOrg, // Organization settings. Settings, Description, DefaultRoleLabel, DefaultRoleHelp, MembersCanCreate, SaveSettings, DeleteOrg, DeleteOrgIntro, // Members. Members, Teams, Organization, MemberHeader, Role, RoleOwner, RoleMember, Leave, AddMember, AddMemberButton, OwnersHelp, // Teams. TeamsIntro, NoTeamsYet, NewTeam, CoversAllRepos, CreateTeam, SaveTeam, DeleteTeam, NoTeamMembers, AddToTeam, Repositories, NoTeamRepos, Unlink, Repository, LinkRepository, AllRepositories, LinkedRepositories, // Role words shown in selects and coverage text. The stored words stay English. RoleNone, RoleRead, RoleWrite, RoleTriage, RoleMaintain, RoleAdmin, // Explore. Pages, Previous, Next, PublicReposIntro, Organizations, SearchPublicRepos, Search, SortBy, SortNav, SortRecentlyUpdated, SortMostStars, NoPublicReposMatch, // Profile. LocalTime, AllMembers, NoMembers, NoVisibleRepos, Starred, NoVisibleStarred, // Dashboard and landing. Dashboard, Home, LandingTagline, LogIn, SetUpForge, YourRepositories, NoReposYet, } pub fn t(lang: Lang, key: K) -> &'static str { use K::*; use Lang::*; match (key, lang) { (NoticeSettingsSaved, En) => "Settings saved.", (NoticeSettingsSaved, Tr) => "Ayarlar kaydedildi.", (NoticeMemberAdded, En) => "Member added.", (NoticeMemberAdded, Tr) => "Üye eklendi.", (NoticeRoleUpdated, En) => "Role updated.", (NoticeRoleUpdated, Tr) => "Rol güncellendi.", (NoticeMemberRemoved, En) => "Member removed.", (NoticeMemberRemoved, Tr) => "Üye çıkarıldı.", (NoticeTeamCreated, En) => "Team created.", (NoticeTeamCreated, Tr) => "Takım oluşturuldu.", (NoticeTeamSaved, En) => "Team saved.", (NoticeTeamSaved, Tr) => "Takım kaydedildi.", (NoticeTeamDeleted, En) => "Team deleted.", (NoticeTeamDeleted, Tr) => "Takım silindi.", (NoticeTeamMemberAdded, En) => "Member added to the team.", (NoticeTeamMemberAdded, Tr) => "Üye takıma eklendi.", (NoticeTeamMemberRemoved, En) => "Member removed from the team.", (NoticeTeamMemberRemoved, Tr) => "Üye takımdan çıkarıldı.", (NoticeTeamRepoAdded, En) => "Repository linked to the team.", (NoticeTeamRepoAdded, Tr) => "Depo takıma bağlandı.", (NoticeTeamRepoRemoved, En) => "Repository unlinked from the team.", (NoticeTeamRepoRemoved, Tr) => "Deponun takım bağlantısı kaldırıldı.", (NoticeEmptyUsername, En) => "Enter a username.", (NoticeEmptyUsername, Tr) => "Bir kullanıcı adı girin.", (NoticeUnknownUser, En) => "No person has that username.", (NoticeUnknownUser, Tr) => "Bu kullanıcı adına sahip bir kişi yok.", (NoticeAlreadyMember, En) => "That person is already a member.", (NoticeAlreadyMember, Tr) => "Bu kişi zaten bir üye.", (NoticeNotMember, En) => "That person is not a member of this organization.", (NoticeNotMember, Tr) => "Bu kişi bu kuruluşun üyesi değil.", (NoticeLastOwner, En) => "An organization needs at least one owner.", (NoticeLastOwner, Tr) => "Bir kuruluşun en az bir sahibi olmalı.", (NoticeInvalidRole, En) => "Choose a valid role.", (NoticeInvalidRole, Tr) => "Geçerli bir rol seçin.", (NoticeInvalidName, En) => "Choose a valid name.", (NoticeInvalidName, Tr) => "Geçerli bir ad seçin.", (NoticeTeamDescriptionLength, En) => "A team description is at most 350 characters.", (NoticeTeamDescriptionLength, Tr) => "Takım açıklaması en fazla 350 karakter olabilir.", (NoticeTeamExists, En) => "A team with this name already exists.", (NoticeTeamExists, Tr) => "Bu adla bir takım zaten var.", (NoticeAlreadyInTeam, En) => "That person is already in this team.", (NoticeAlreadyInTeam, Tr) => "Bu kişi zaten bu takımda.", (NoticeNotInOrg, En) => "Only members of the organization can join its teams.", (NoticeNotInOrg, Tr) => "Yalnızca kuruluşun üyeleri takımlarına katılabilir.", (NoticeNotOwned, En) => "Only repositories this organization owns can join its teams.", (NoticeNotOwned, Tr) => "Yalnızca bu kuruluşa ait depolar takımlarına katılabilir.", (NoticeAlreadyLinked, En) => "This team already covers that repository.", (NoticeAlreadyLinked, Tr) => "Bu takım bu depoyu zaten kapsıyor.", (NoticeHasRepos, En) => "Transfer or delete the organization's repositories first.", (NoticeHasRepos, Tr) => "Önce kuruluşun depolarını devredin veya silin.", (NoticeConfirmName, En) => "Type the organization's name exactly to delete it.", (NoticeConfirmName, Tr) => "Kuruluşu silmek için adını tam olarak yazın.", (NoticeDescriptionLength, En) => "The description is longer than 2000 characters.", (NoticeDescriptionLength, Tr) => "Açıklama 2000 karakterden uzun.", (Save, En) => "Save", (Save, Tr) => "Kaydet", (Remove, En) => "Remove", (Remove, Tr) => "Kaldır", (Username, En) => "Username", (Username, Tr) => "Kullanıcı adı", (Name, En) => "Name", (Name, Tr) => "Ad", (Explore, En) => "Explore", (Explore, Tr) => "Keşfet", (NewRepository, En) => "New repository", (NewRepository, Tr) => "Yeni depo", (NewOrganization, En) => "New organization", (NewOrganization, Tr) => "Yeni kuruluş", (NewOrgIntro, En) => { "An organization owns repositories and shares them with its members through teams. You become its first owner." } (NewOrgIntro, Tr) => { "Kuruluş depolara sahip olur ve bunları takımları aracılığıyla üyeleriyle paylaşır. Kuruluşun ilk sahibi siz olursunuz." } (OrgName, En) => "Organization name", (OrgName, Tr) => "Kuruluş adı", (DescriptionOptional, En) => "Description (optional)", (DescriptionOptional, Tr) => "Açıklama (isteğe bağlı)", (CreateOrg, En) => "Create organization", (CreateOrg, Tr) => "Kuruluş oluştur", (Settings, En) => "Settings", (Settings, Tr) => "Ayarlar", (Description, En) => "Description", (Description, Tr) => "Açıklama", (DefaultRoleLabel, En) => "Default role on the organization's repositories", (DefaultRoleLabel, Tr) => "Kuruluş depolarında varsayılan rol", (DefaultRoleHelp, En) => { "Members get this role on every repository the organization owns, unless a team gives them more. Owners always have admin." } (DefaultRoleHelp, Tr) => { "Üyeler, bir takım daha fazla yetki vermedikçe kuruluşa ait her depoda bu rolü alır. Sahipler her zaman yönetici yetkisine sahiptir." } (MembersCanCreate, En) => "Members can create repositories for this organization", (MembersCanCreate, Tr) => "Üyeler bu kuruluş için depo oluşturabilir", (SaveSettings, En) => "Save settings", (SaveSettings, Tr) => "Ayarları kaydet", (DeleteOrg, En) => "Delete organization", (DeleteOrg, Tr) => "Kuruluşu sil", (DeleteOrgIntro, En) => { "Deleting removes the organization, its members and its teams. It is refused while the organization owns repositories." } (DeleteOrgIntro, Tr) => { "Silme işlemi kuruluşu, üyelerini ve takımlarını kaldırır. Kuruluşun depoları varken reddedilir." } (Members, En) => "Members", (Members, Tr) => "Üyeler", (Teams, En) => "Teams", (Teams, Tr) => "Takımlar", (Organization, En) => "Organization", (Organization, Tr) => "Kuruluş", (MemberHeader, En) => "Member", (MemberHeader, Tr) => "Üye", (Role, En) => "Role", (Role, Tr) => "Rol", (RoleOwner, En) => "owner", (RoleOwner, Tr) => "sahip", (RoleMember, En) => "member", (RoleMember, Tr) => "üye", (Leave, En) => "Leave", (Leave, Tr) => "Ayrıl", (AddMember, En) => "Add a member", (AddMember, Tr) => "Bir üye ekle", (AddMemberButton, En) => "Add member", (AddMemberButton, Tr) => "Üye ekle", (OwnersHelp, En) => { "Owners manage the organization, its teams and its settings. Members get the repository access their teams give them." } (OwnersHelp, Tr) => { "Sahipler kuruluşu, takımlarını ve ayarlarını yönetir. Üyeler, takımlarının verdiği depo erişimini alır." } (TeamsIntro, En) => { "A team gives its members a role on the repositories it covers: every repository the organization owns when the team covers all of them, otherwise only the repositories linked to it." } (TeamsIntro, Tr) => { "Takım, üyelerine kapsadığı depolarda bir rol verir: takım kuruluşun tüm depolarını kapsıyorsa kuruluşa ait her depo, aksi halde yalnızca takıma bağlı depolar." } (NoTeamsYet, En) => "No teams yet.", (NoTeamsYet, Tr) => "Henüz takım yok.", (NewTeam, En) => "New team", (NewTeam, Tr) => "Yeni takım", (CoversAllRepos, En) => "Covers all of the organization's repositories", (CoversAllRepos, Tr) => "Kuruluşun tüm depolarını kapsar", (CreateTeam, En) => "Create team", (CreateTeam, Tr) => "Takım oluştur", (SaveTeam, En) => "Save team", (SaveTeam, Tr) => "Takımı kaydet", (DeleteTeam, En) => "Delete team", (DeleteTeam, Tr) => "Takımı sil", (NoTeamMembers, En) => "No members in this team yet.", (NoTeamMembers, Tr) => "Bu takımda henüz üye yok.", (AddToTeam, En) => "Add to team", (AddToTeam, Tr) => "Takıma ekle", (Repositories, En) => "Repositories", (Repositories, Tr) => "Depolar", (NoTeamRepos, En) => "No repositories are linked to this team.", (NoTeamRepos, Tr) => "Bu takıma bağlı depo yok.", (Unlink, En) => "Unlink", (Unlink, Tr) => "Bağlantıyı kaldır", (Repository, En) => "Repository", (Repository, Tr) => "Depo", (LinkRepository, En) => "Link repository", (LinkRepository, Tr) => "Depoyu bağla", (AllRepositories, En) => "all repositories", (AllRepositories, Tr) => "tüm depolarda", (LinkedRepositories, En) => "linked repositories", (LinkedRepositories, Tr) => "bağlı depolarda", (RoleNone, En) => "none", (RoleNone, Tr) => "yok", (RoleRead, En) => "read", (RoleRead, Tr) => "okuma", (RoleWrite, En) => "write", (RoleWrite, Tr) => "yazma", (RoleTriage, En) => "triage", (RoleTriage, Tr) => "triyaj", (RoleMaintain, En) => "maintain", (RoleMaintain, Tr) => "bakım", (RoleAdmin, En) => "admin", (RoleAdmin, Tr) => "yönetici", (Pages, En) => "Pages", (Pages, Tr) => "Sayfalar", (Previous, En) => "Previous", (Previous, Tr) => "Önceki", (Next, En) => "Next", (Next, Tr) => "Sonraki", (PublicReposIntro, En) => "Public repositories on this forge.", (PublicReposIntro, Tr) => "Bu forge üzerindeki herkese açık depolar.", (Organizations, En) => "Organizations", (Organizations, Tr) => "Kuruluşlar", (SearchPublicRepos, En) => "Search public repositories", (SearchPublicRepos, Tr) => "Herkese açık depolarda ara", (Search, En) => "Search", (Search, Tr) => "Ara", (SortBy, En) => "Sort by", (SortBy, Tr) => "Sırala", (SortNav, En) => "Sort", (SortNav, Tr) => "Sırala", (SortRecentlyUpdated, En) => "Recently updated", (SortRecentlyUpdated, Tr) => "Son güncellenenler", (SortMostStars, En) => "Most stars", (SortMostStars, Tr) => "En çok yıldızlananlar", (NoPublicReposMatch, En) => "No public repositories match.", (NoPublicReposMatch, Tr) => "Aramayla eşleşen herkese açık depo yok.", (LocalTime, En) => "Local time: ", (LocalTime, Tr) => "Yerel saat: ", (AllMembers, En) => "All members", (AllMembers, Tr) => "Tüm üyeler", (NoMembers, En) => "No members.", (NoMembers, Tr) => "Üye yok.", (NoVisibleRepos, En) => "No visible repositories.", (NoVisibleRepos, Tr) => "Görünür depo yok.", (Starred, En) => "Starred", (Starred, Tr) => "Yıldızlılar", (NoVisibleStarred, En) => "No visible starred repositories.", (NoVisibleStarred, Tr) => "Görünür yıldızlı depo yok.", (Dashboard, En) => "Dashboard", (Dashboard, Tr) => "Pano", (Home, En) => "Home", (Home, Tr) => "Ana sayfa", (LandingTagline, En) => "Self-hosted git repositories with a small, fast web interface.", (LandingTagline, Tr) => { "Kendi sunucunuzda barındırılan git depoları, küçük ve hızlı bir web arayüzüyle." } (LogIn, En) => "Log in", (LogIn, Tr) => "Giriş yap", (SetUpForge, En) => "Set up forge", (SetUpForge, Tr) => "forge'u kur", (YourRepositories, En) => "Your repositories", (YourRepositories, Tr) => "Depolarınız", (NoReposYet, En) => "You have no repositories yet.", (NoReposYet, Tr) => "Henüz deponuz yok.", } } /// The text for a role word from a select or a coverage line. Unknown words pass through. pub fn role_name(lang: Lang, word: &'static str) -> &'static str { let key = match word { "none" => K::RoleNone, "read" => K::RoleRead, "write" => K::RoleWrite, "triage" => K::RoleTriage, "maintain" => K::RoleMaintain, "admin" => K::RoleAdmin, _ => return word, }; t(lang, key) } /// A team's role and coverage, in words: "write on all repositories", or "tüm depolarda yazma". pub fn coverage_text(lang: Lang, role: &'static str, all_repos: bool) -> String { let scope = t( lang, if all_repos { K::AllRepositories } else { K::LinkedRepositories }, ); let role = role_name(lang, role); match lang { Lang::En => format!("{role} on {scope}"), Lang::Tr => format!("{scope} {role}"), } } /// The "too long" rejection for an organization description. pub fn description_too_long(lang: Lang, max: usize) -> String { match lang { Lang::En => format!("description must be at most {max} characters"), Lang::Tr => format!("Açıklama en fazla {max} karakter olabilir."), } } /// The label that asks for the org's name before deleting it. pub fn type_to_confirm(lang: Lang, name: &str) -> String { match lang { Lang::En => format!("Type {name} to confirm"), Lang::Tr => format!("Onaylamak için {name} yazın"), } } /// The page title: the org name, a separator, then the section name. pub fn page_title(lang: Lang, org: &str, section: K) -> String { format!("{org} \u{b7} {}", t(lang, section)) } /// The label for a member's role select. pub fn role_for(lang: Lang, user: &str) -> String { match lang { Lang::En => format!("Role for {user}"), Lang::Tr => format!("{user} için rol"), } } /// The member and team counts on a profile. pub fn members_and_teams(lang: Lang, members: usize, teams: usize) -> String { match lang { Lang::En => format!("{members} members \u{b7} {teams} teams"), Lang::Tr => format!("{members} üye \u{b7} {teams} takım"), } } /// "3 repositories", or "3 depo" in Turkish. pub fn repo_count(lang: Lang, total: u64) -> String { match lang { Lang::En => format!("{total} repositories"), Lang::Tr => format!("{total} depo"), } } /// "Page 2 of 5", or "Sayfa 2 / 5" in Turkish. pub fn page_of(lang: Lang, page: u64, pages: u64) -> String { match lang { Lang::En => format!("Page {page} of {pages}"), Lang::Tr => format!("Sayfa {page} / {pages}"), } } /// The updated note after a repository's stars: " · updated 3 days ago", or " · 3 gün önce güncellendi". pub fn updated_text(lang: Lang, when: &str) -> String { match lang { Lang::En => format!(" \u{b7} updated {when}"), Lang::Tr => format!(" \u{b7} {when} güncellendi"), } } #[cfg(test)] mod tests { use super::*; /// Every key, for the coverage tests. Keep it in step with the enum. const ALL: &[K] = &[ K::NoticeSettingsSaved, K::NoticeMemberAdded, K::NoticeRoleUpdated, K::NoticeMemberRemoved, K::NoticeTeamCreated, K::NoticeTeamSaved, K::NoticeTeamDeleted, K::NoticeTeamMemberAdded, K::NoticeTeamMemberRemoved, K::NoticeTeamRepoAdded, K::NoticeTeamRepoRemoved, K::NoticeEmptyUsername, K::NoticeUnknownUser, K::NoticeAlreadyMember, K::NoticeNotMember, K::NoticeLastOwner, K::NoticeInvalidRole, K::NoticeInvalidName, K::NoticeTeamDescriptionLength, K::NoticeTeamExists, K::NoticeAlreadyInTeam, K::NoticeNotInOrg, K::NoticeNotOwned, K::NoticeAlreadyLinked, K::NoticeHasRepos, K::NoticeConfirmName, K::NoticeDescriptionLength, K::Save, K::Remove, K::Username, K::Name, K::Explore, K::NewRepository, K::NewOrganization, K::NewOrgIntro, K::OrgName, K::DescriptionOptional, K::CreateOrg, K::Settings, K::Description, K::DefaultRoleLabel, K::DefaultRoleHelp, K::MembersCanCreate, K::SaveSettings, K::DeleteOrg, K::DeleteOrgIntro, K::Members, K::Teams, K::Organization, K::MemberHeader, K::Role, K::RoleOwner, K::RoleMember, K::Leave, K::AddMember, K::AddMemberButton, K::OwnersHelp, K::TeamsIntro, K::NoTeamsYet, K::NewTeam, K::CoversAllRepos, K::CreateTeam, K::SaveTeam, K::DeleteTeam, K::NoTeamMembers, K::AddToTeam, K::Repositories, K::NoTeamRepos, K::Unlink, K::Repository, K::LinkRepository, K::AllRepositories, K::LinkedRepositories, K::RoleNone, K::RoleRead, K::RoleWrite, K::RoleTriage, K::RoleMaintain, K::RoleAdmin, K::Pages, K::Previous, K::Next, K::PublicReposIntro, K::Organizations, K::SearchPublicRepos, K::Search, K::SortBy, K::SortNav, K::SortRecentlyUpdated, K::SortMostStars, K::NoPublicReposMatch, K::LocalTime, K::AllMembers, K::NoMembers, K::NoVisibleRepos, K::Starred, K::NoVisibleStarred, K::Dashboard, K::Home, K::LandingTagline, K::LogIn, K::SetUpForge, K::YourRepositories, K::NoReposYet, ]; #[test] fn every_key_has_text_in_both_languages() { for key in ALL { assert!(!t(Lang::En, *key).is_empty(), "{key:?} has no English"); assert!(!t(Lang::Tr, *key).is_empty(), "{key:?} has no Turkish"); } } #[test] fn turkish_differs_from_english_for_most_keys() { let differing = ALL .iter() .filter(|key| t(Lang::En, **key) != t(Lang::Tr, **key)) .count(); assert!(differing >= 3, "only {differing} keys are translated"); assert_eq!(t(Lang::Tr, K::NoTeamsYet), "Henüz takım yok."); } #[test] fn helpers_keep_the_english_sentences() { assert_eq!( coverage_text(Lang::En, "write", true), "write on all repositories" ); assert_eq!( coverage_text(Lang::En, "read", false), "read on linked repositories" ); assert_eq!( coverage_text(Lang::Tr, "read", false), "bağlı depolarda okuma" ); assert_eq!(page_of(Lang::En, 2, 5), "Page 2 of 5"); assert_eq!( updated_text(Lang::En, "3 days ago"), " \u{b7} updated 3 days ago" ); assert_eq!( updated_text(Lang::Tr, "3 gün önce"), " \u{b7} 3 gün önce güncellendi" ); assert_eq!(repo_count(Lang::En, 3), "3 repositories"); assert_eq!( members_and_teams(Lang::En, 2, 1), "2 members \u{b7} 1 teams" ); assert_eq!(type_to_confirm(Lang::En, "acme"), "Type acme to confirm"); assert_eq!( description_too_long(Lang::En, 2000), "description must be at most 2000 characters" ); } }