From 9d291ce5f962c52c8e6a077ba6d696656b6e422c Mon Sep 17 00:00:00 2001 From: william Date: Thu, 4 Aug 2016 14:07:34 +0800 Subject: 1.8.x tranditional chinese translation after user experience --- .../gitblit/wicket/GitBlitWebApp_zh_TW.properties | 1461 ++++++++++---------- 1 file changed, 739 insertions(+), 722 deletions(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties index 16a9c864..b2711cea 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties @@ -1,772 +1,789 @@ #! -#! created/edited by Popeye version 0.54 (popeye.sourceforge.net) +#! created/edited by Popeye version 0.55 (https://github.com/koppor/popeye) #! encoding:ISO-8859-1 -gb.about = \u95dc\u65bc -gb.acceptNewPatchsets = \u5141\u8a31\u88dc\u4e01 -gb.acceptNewPatchsetsDescription = \u63a5\u53d7\u5230\u7248\u672c\u5009\u9032\u884c\u4fee\u88dc\u52d5\u4f5c -gb.acceptNewTickets = \u5141\u8a31\u5efa\u7acb\u4efb\u52d9\u55ae -gb.acceptNewTicketsDescription = \u5141\u8a31\u65b0\u589e"\u81ed\u87f2","\u512a\u5316","\u4efb\u52d9"\u5404\u985e\u578b\u4efb\u52d9\u55ae -gb.accessDenied = \u62d2\u7d55\u5b58\u53d6 -gb.accessLevel = \u5b58\u53d6\u7b49\u7d1a -gb.accessPermissions = \u5b58\u53d6\u6b0a\u9650 -gb.accessPermissionsDescription = restrict access by users and teams -gb.accessPermissionsForTeamDescription = set team members and grant access to specific restricted repositories -gb.accessPermissionsForUserDescription = set team memberships or grant access to specific restricted repositories -gb.accessPolicy = \u5b58\u53d6\u653f\u7b56 -gb.accessPolicyDescription = \u9078\u64c7\u7528\u4f86\u63a7\u5236\u6587\u4ef6\u5eab\u7684\u5b58\u53d6\u653f\u7b56\u4ee5\u53ca\u6b0a\u9650\u8a2d\u5b9a -gb.accessRestriction = \u9650\u5236\u5b58\u53d6 -gb.accountPreferences = \u5e33\u865f\u8a2d\u5b9a -gb.accountPreferencesDescription = \u8a2d\u5b9a\u5e33\u865f\u9810\u8a2d\u503c -gb.action = \u52d5\u4f5c -gb.active = \u6d3b\u52d5 -gb.activeAuthors = \u6d3b\u8e8d\u7528\u6236 -gb.activeRepositories = \u6d3b\u8e8d\u7248\u672c\u5eab -gb.activity = \u6d3b\u52d5 -gb.add = \u65b0\u589e -gb.addComment = \u65b0\u589e\u8a3b\u89e3 -gb.addedNCommits = {0}\u500b\u6a94\u6848\u63d0\u4ea4\u5b8c\u7562 -gb.addedOneCommit = \u63d0\u4ea41\u500b\u6a94\u6848 -gb.addition = addition -gb.addSshKey = \u65b0\u589e SSH Key -gb.administration = \u7ba1\u7406\u6b0a\u9650 -gb.administrator = \u7ba1\u7406\u54e1 -gb.administratorPermission = Gitblit \u7ba1\u7406\u54e1 -gb.affiliationChanged = affiliation changed -gb.age = \u6642\u9593 -gb.all = \u5168\u90e8 -gb.allBranches = \u6240\u6709\u5206\u652f -gb.allowAuthenticatedDescription = \u6279\u51c6 RW+ \u6b0a\u9650\u7d66\u4e88\u5c08\u6848\u6210\u54e1 -gb.allowForks = \u5141\u8a31\u5efa\u7acb\u5206\u652f(forks) -gb.allowForksDescription = \u5141\u8a31\u5df2\u6388\u6b0a\u7684\u4f7f\u7528\u8005\u5f9e\u6587\u4ef6\u5eab\u5efa\u7acb\u5206\u652f(fork) -gb.allowNamedDescription = grant fine-grained permissions to named users or teams -gb.allProjects = \u5168\u90e8\u7fa4\u7d44 -gb.allTags = \u6240\u6709\u6a19\u7c64 -gb.anonymousCanNotPropose = \u533f\u540d\u8005\u4e0d\u80fd\u63d0\u4f9b\u88dc\u4e01 -gb.anonymousPolicy = \u533f\u540d\u72c0\u614b\u53ef\u4ee5View, Clone\u8207Push -gb.anonymousPolicyDescription = \u4efb\u4f55\u4eba\u53ef\u6aa2\u8996,\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u6587\u4ef6\u5230\u6587\u4ef6\u5eab -gb.anonymousUser= \u533f\u540d\u72c0\u614b -gb.any = \u4efb\u4f55 -gb.approve = \u901a\u904e -gb.at = at -gb.attributes = \u5c6c\u6027 -gb.authenticatedPushPolicy = Restrict Push (Authenticated) -gb.authenticatedPushPolicyDescription = \u4efb\u4f55\u4eba\u53ef\u4ee5\u6aa2\u8996\u8207\u8907\u88fd(clone).\u6240\u6709\u6587\u4ef6\u5eab\u6210\u54e1\u7686\u6709RW+\u8207\u63a8\u9001(push)\u529f\u80fd. +gb.repository = \u7248\u672c\u5eab +gb.owner = \u64c1\u6709\u8005 +gb.description = \u6982\u8ff0 +gb.lastChange = \u6700\u8fd1\u4fee\u6539 +gb.refs = \u6bd4\u5c0d +gb.tag = \u6a19\u7c64 +gb.tags = \u6a19\u7c64 gb.author = \u4f5c\u8005 -gb.authored = \u5df2\u6388\u6b0a -gb.authorizationControl = \u6388\u6b0a\u7ba1\u63a7 -gb.available = \u53ef\u7528 -gb.blame = \u7a76\u67e5 -gb.blinkComparator = Blink comparator -gb.blob = \u5340\u584a -gb.body = body -gb.bootDate = \u555f\u52d5\u65e5 -gb.branch = \u5206\u652f +gb.committer = \u78ba\u8a8d\u8005 +gb.commit = \u63d0\u4ea4 +gb.age = \u6642\u9593 +gb.tree = \u76ee\u9304 +gb.parent = \u4e0a\u500b\u7248\u672c +gb.url = URL +gb.history = \u6b77\u53f2 +gb.raw = \u539f\u59cb +gb.object = \u7269\u4ef6 +gb.ticketId = \u4efb\u52d9ID +gb.ticketAssigned = \u5df2\u6307\u5b9a +gb.ticketOpenDate = \u767c\u884c\u65e5 +gb.ticketState = +gb.ticketComments = \u8a3b\u89e3 +gb.view = \u6aa2\u8996 +gb.local = \u672c\u5730\u7aef +gb.remote = \u9060\u7aef gb.branches = \u5206\u652f -gb.branchStats = \u9019\u500b\u5206\u652f{2}\u6709{0}\u500b\u63d0\u4ea4\u4ee5\u53ca{1}\u500b\u6a19\u7c64 -gb.browse = \u700f\u89bd -gb.bugTickets = \u81ed\u87f2 -gb.busyCollectingGarbage = \u62b1\u6b49,Gitblit\u6b63\u5728\u56de\u6536\u7cfb\u7d71\u8cc7\u6e90\u4e2d:{0} -gb.byNAuthors = \u7d93\u7531{0}\u500b\u4f5c\u8005 -gb.byOneAuthor = \u7d93\u7531{0} -gb.caCompromise = CA compromise +gb.patch = \u4fee\u88dc\u6a94 +gb.diff = \u5dee\u7570 +gb.log = \u65e5\u8a8c +gb.moreLogs = \u66f4\u591a\u63d0\u4ea4 ... +gb.allTags = \u6240\u6709\u6a19\u7c64 +gb.allBranches = \u6240\u6709\u5206\u652f +gb.summary = \u532f\u7e3d +gb.ticket = \u4efb\u52d9 +gb.newRepository = \u5efa\u7acb\u7248\u672c\u5eab +gb.newUser = \u5efa\u7acb\u4f7f\u7528\u8005 +gb.commitdiff = \u5dee\u7570 +gb.tickets = \u4efb\u52d9 +gb.pageFirst = \u7b2c\u4e00\u7b46 +gb.pagePrevious = \u4e0a\u4e00\u9801 +gb.pageNext = \u4e0b\u4e00\u9801 +gb.head = HEAD +gb.blame = \u8ffd\u67e5 +gb.login = \u767b\u5165 +gb.logout = \u767b\u51fa +gb.username = \u4f7f\u7528\u8005\u540d\u7a31 +gb.password = \u5bc6\u78bc +gb.tagger = \u6a19\u8a18\u8005 +gb.moreHistory = \u66f4\u591a\u6b77\u53f2\u7d00\u9304... +gb.difftocurrent = \u6bd4\u5c0d\u5dee\u7570 +gb.search = \u641c\u5c0b +gb.searchForAuthor = \u4f9d\u5be9\u6838\u8005\u641c\u5c0b\u63d0\u4ea4\u5167\u5bb9 +gb.searchForCommitter = \u4f9d\u63d0\u4ea4\u8005\u641c\u5c0b\u63d0\u4ea4\u5167\u5bb9 +gb.addition = \u589e\u52a0 +gb.modification = \u4fee\u6539 +gb.deletion = \u522a\u9664 +gb.rename = \u6539\u540d\u7a31 +gb.metrics = \u7d71\u8a08 +gb.stats = \u7d71\u8a08 +gb.markdown = markdown +gb.changedFiles = \u5df2\u8b8a\u66f4\u904e\u7684\u6a94\u6848 +gb.filesAdded = \u65b0\u589e{0}\u500b\u6a94\u6848 +gb.filesModified = \u4fee\u6539{0}\u500b\u6a94\u6848 +gb.filesDeleted = \u522a\u9664{0}\u500b\u6a94\u6848 +gb.filesCopied = \u8907\u88fd{0}\u500b\u6a94\u6848 +gb.filesRenamed = \u4fee\u6539{0}\u500b\u6a94\u6848\u540d\u7a31 +gb.missingUsername = \u7121\u4f7f\u7528\u8005\u540d\u7a31 +gb.edit = \u7de8\u8f2f +gb.searchTypeTooltip = \u9078\u64c7\u641c\u5c0b\u985e\u578b +gb.searchTooltip = \u641c\u5c0b{0} +gb.delete = \u522a\u9664 +gb.docs = \u6a94\u6848\u5340 +gb.accessRestriction = \u9650\u5236\u5b58\u53d6 +gb.name = \u540d\u5b57 +gb.enableTickets = \u555f\u7528\u4efb\u52d9(Ticket)\u7cfb\u7d71 +gb.enableDocs = \u555f\u7528\u8aaa\u660e\u6587\u4ef6 +gb.save = \u5132\u5b58 +gb.showRemoteBranches = \u986f\u793a\u9060\u7aef\u5206\u652f +gb.editUsers = \u4fee\u6539\u5e33\u865f +gb.confirmPassword = \u78ba\u8a8d\u5bc6\u78bc +gb.restrictedRepositories = \u53d7\u9650\u5236\u7684\u7248\u672c\u5eab gb.canAdmin = \u53ef\u7ba1\u7406 +gb.notRestricted = \u533f\u540d\u72c0\u614b\u53ef\u4ee5View, Clone\u8207Push +gb.pushRestricted = authenticated push +gb.cloneRestricted = authenticated clone & push +gb.viewRestricted = authenticated view, clone, & push +gb.useTicketsDescription = readonly, distributed Ticgit issues +gb.useDocsDescription = \u8a08\u7b97\u7248\u672c\u5eab\u88e1\u9762\u7684Markdown\u6a94\u6848 +gb.showRemoteBranchesDescription = \u986f\u793a\u9060\u7aef\u5206\u652f(branches) gb.canAdminDescription = \u53ef\u7ba1\u7406Gitblit\u4f3a\u670d\u5668 +gb.permittedUsers = \u5141\u8a31\u7528\u6236 +gb.isFrozen = \u51cd\u7d50\u63a5\u6536 +gb.isFrozenDescription = \u7981\u6b62\u63a8\u9001(push) +gb.zip = zip\u58d3\u7e2e\u6a94 +gb.showReadme = \u986f\u793areadme\u6587\u4ef6 +gb.showReadmeDescription = \u5728\u532f\u7e3d\u9801\u9762\u4e2d\u986f\u793a"readme"(markdown\u683c\u5f0f) +gb.nameDescription = \u4f7f\u7528"/"\u505a\u70ba\u7248\u672c\u5eab\u7fa4\u7d44\u5206\u985e. \u5982: library/mycoolib.git +gb.ownerDescription = \u64c1\u6709\u8005\u53ef\u4fee\u6539\u7248\u672c\u5eab\u8a2d\u5b9a\u503c +gb.blob = \u5340\u584a +gb.commitActivityTrend = \u63d0\u4ea4\u8da8\u52e2 +gb.commitActivityDOW = \u6bcf(\u65e5)\u9031\u63d0\u4ea4 +gb.commitActivityAuthors = \u63d0\u4ea4\u6d3b\u8e8d\u7387(\u4f7f\u7528\u8005) +gb.feed = \u8cc7\u6599\u8a02\u95b1 gb.cancel = \u53d6\u6d88 -gb.canCreate = \u53ef\u5efa\u7acb -gb.canCreateDescription = \u80fd\u5920\u5efa\u7acb\u79c1\u4eba\u6587\u4ef6\u5eab -gb.canFork = \u53ef\u5efa\u7acb\u5206\u652f(fork) -gb.canForkDescription = \u53ef\u4ee5\u5efa\u7acb\u6587\u4ef6\u5eab\u5206\u652f(fork),\u4e26\u4e14\u8907\u88fd\u5230\u79c1\u4eba\u6587\u4ef6\u5eab\u4e2d -gb.canNotLoadRepository = \u7121\u6cd5\u8f09\u5165\u7248\u672c\u5eab -gb.canNotProposePatchset = \u4e0d\u80fd\u63d0\u4f9b\u88dc\u4e01 -gb.certificate = \u8b49\u66f8 -gb.certificateRevoked = \u8b49\u66f8{0,number,0} \u5df2\u7d93\u88ab\u53d6\u6d88 -gb.certificates = \u8b49\u66f8 -gb.cessationOfOperation = cessation of operation -gb.changedFiles = \u5df2\u8b8a\u66f4\u904e\u7684\u6a94\u6848 -gb.changedStatus = changed the status gb.changePassword = \u4fee\u6539\u5bc6\u78bc -gb.checkout = \u6aa2\u51fa(checkout) -gb.checkoutStep1 = Fetch the current patchset \u2014 run this from your project directory -gb.checkoutStep2 = \u5c07\u8a72\u88dc\u4e01\u8f49\u51fa\u5230\u65b0\u7684\u5206\u652f\u7136\u5f8c\u7528\u4f86\u6aa2\u8996 -gb.checkoutViaCommandLine = \u4f7f\u7528\u6307\u4ee4Checkout -gb.checkoutViaCommandLineNote = \u4f60\u53ef\u4ee5\u5f9e\u4f60\u6587\u4ef6\u5eab\u4e2dcheckout\u4e00\u4efd,\u7136\u5f8c\u9032\u884c\u6e2c\u8a66 -gb.clearCache = \u6e05\u9664\u5feb\u53d6 -gb.clientCertificateBundleSent = {0}\u7684\u7528\u6236\u8b49\u66f8\u5df2\u5bc4\u767c -gb.clientCertificateGenerated = \u6210\u529f\u7522\u751f{0}\u7684\u65b0\u8b49\u66f8 +gb.isFederated = \u5df2\u7d93federated +gb.federateThis = \u8207\u6b64\u7248\u672c\u5eab federate +gb.federateOrigin = federate the origin +gb.excludeFromFederation = exclude from federation +gb.excludeFromFederationDescription = \u7981\u6b62federated \u7684Gitblit\u4f3a\u670d\u5668 +gb.tokens = federation tokens +gb.tokenAllDescription = \u6240\u6709\u7248\u672c\u5eab,\u4f7f\u7528\u8005\u8207\u8a2d\u5b9a +gb.tokenUnrDescription = \u6240\u6709\u7248\u672c\u5eab\u8207\u4f7f\u7528\u8005 +gb.tokenJurDescription = \u6240\u6709\u7248\u672c\u5eab +gb.federatedRepositoryDefinitions = \u7248\u672c\u5eab\u5b9a\u7fa9 +gb.federatedUserDefinitions = \u4f7f\u7528\u8005\u5b9a\u7fa9 +gb.federatedSettingDefinitions = setting definitions +gb.proposals = federation proposals +gb.received = \u5df2\u63a5\u6536 +gb.type = \u985e\u578b +gb.token = token +gb.repositories = \u7248\u672c\u5eab +gb.proposal = \u63d0\u6848 +gb.frequency = \u983b\u7387 +gb.folder = \u76ee\u9304 +gb.lastPull = \u4e0a\u6b21\u4e0b\u8f09(pull) +gb.nextPull = \u4e0b\u4e00\u500b pull +gb.inclusions = inclusions +gb.exclusions = \u6392\u9664 +gb.registration = \u8a3b\u518a +gb.registrations = federation registrations +gb.sendProposal = \u63d0\u6848 +gb.status = \u72c0\u614b +gb.origin = origin +gb.headRef = \u9810\u8a2d\u5206\u652f(HEAD) +gb.headRefDescription = \u9810\u8a2d\u5206\u652f\u5c07\u6703\u8907\u88fd\u4ee5\u53ca\u986f\u793a\u5230\u532f\u7e3d\u9801\u9762 +gb.federationStrategy = federation \u7b56\u7565 +gb.federationRegistration = federation registration +gb.federationResults = federation pull results +gb.federationSets = federation sets +gb.message = \u8a0a\u606f +gb.myUrlDescription = \u60a8Gitblit\u4f3a\u670d\u5668\u7684\u516c\u958bURL +gb.destinationUrl = \u50b3\u9001 +gb.destinationUrlDescription = \u50b3\u9001Gitblit\u9023\u7d50\u5230\u4f60\u7684\u5c08\u6848(proposal) +gb.users = \u4f7f\u7528\u8005 +gb.federation = federation +gb.error = \u932f\u8aa4 +gb.refresh = \u91cd\u6574 +gb.browse = \u700f\u89bd gb.clone = \u8907\u88fd(clone) -gb.clonePermission = {0} \u8907\u88fd(clone) -gb.clonePolicy = Restrict Clone & Push -gb.clonePolicyDescription = \u4efb\u4f55\u4eba\u53ef\u4ee5\u770b\u6587\u4ef6\u5eab. \u4f46\u4f60\u80fd\u5920\u8907\u88fd(clone)\u8207\u63a8\u9001(push) -gb.cloneRestricted = authenticated clone & push -gb.closeBrowser = \u8acb\u95dc\u9589\u700f\u89bd\u5668\u7d50\u675f\u6b64\u767b\u5165\u968e\u6bb5 -gb.closed = \u95dc\u9589 -gb.closedMilestones = \u5df2\u95dc\u9589\u7684\u91cc\u7a0b\u7891(milestones) -gb.combinedMd5Rename = Gitblit\u4f7f\u7528md5\u65b9\u5f0f\u5c07\u5bc6\u78bc\u7de8\u78bc(\u7121\u6cd5\u9084\u539f).\u4f60\u5fc5\u9808\u8f38\u5165\u65b0\u5bc6\u78bc. -gb.comment = \u8a3b\u89e3 -gb.commented = \u5df2\u8a3b\u89e3 -gb.comments = \u8a3b\u89e3 -gb.commit = \u63d0\u4ea4 -gb.commitActivityAuthors = \u63d0\u4ea4\u6d3b\u8e8d\u7387(\u4f7f\u7528\u8005) -gb.commitActivityDOW = \u6bcf(\u65e5)\u9031\u63d0\u4ea4 -gb.commitActivityTrend = \u63d0\u4ea4\u8da8\u52e2\u5716 -gb.commitdiff = \u63d0\u4ea4\u5dee\u7570 -gb.commitIsNull = \u63d0\u4ea4\u5167\u5bb9\u662f\u7a7a\u7684 -gb.commitMessageRenderer = \u63d0\u4ea4\u8a0a\u606f\u5448\u73fe\u65b9\u5f0f -gb.commitMessageRendererDescription = \u63d0\u4ea4\u8a0a\u606f\u53ef\u4ee5\u4f7f\u7528\u6587\u5b57\u6216\u662f\u6a19\u8a18\u8a9e\u8a00(markup)\u5448\u73fe -gb.commits = \u63d0\u4ea4 -gb.commitsInPatchsetN = \u88dc\u4e01 {0} \u7684\u63d0\u4ea4 -gb.commitsTo = {0} commits to -gb.committed = \u5df2\u63d0\u4ea4 -gb.committer = \u78ba\u8a8d\u63d0\u4ea4\u8005 -gb.compare = \u6bd4\u5c0d -gb.compareToMergeBase = \u6bd4\u5c0d\u5f8c,\u5408\u4f75\u5230\u4e3b\u8981\u5de5\u4f5c\u5340 -gb.compareToN = \u8207{0}\u9032\u884c\u6bd4\u5c0d -gb.completeGravatarProfile = \u5b8c\u6210Gravator.com\u4e0a\u7684\u57fa\u672c\u8cc7\u6599\u8a2d\u5b9a -gb.confirmPassword = \u78ba\u8a8d\u5bc6\u78bc -gb.content = \u5167\u5bb9 -gb.copyToClipboard = \u8907\u88fd\u5230\u526a\u8cbc\u677f -gb.couldNotCreateFederationProposal = \u7121\u6cd5\u5efa\u7acb\u4e32\u9023\u7684\u5408\u4f5c\u63d0\u6848 -gb.couldNotFindFederationProposal = \u641c\u5c0b\u4e0d\u5230\u8981\u6c42\u4e32\u9023\u7684\u63d0\u6848 -gb.couldNotFindFederationRegistration = \u627e\u4e0d\u5230\u4e32\u9023\u8a3b\u518a\u55ae -gb.couldNotFindTag = \u627e\u4e0d\u5230\u6a19\u7c64{0} -gb.countryCode = \u570b\u5bb6\u4ee3\u78bc +gb.filter = \u7be9\u9078 gb.create = \u5efa\u7acb -gb.createdBy = created by -gb.createdNewBranch = \u5efa\u7acb\u65b0\u5206\u652f -gb.createdNewPullRequest = created pull request -gb.createdNewTag = \u5efa\u7acb\u65b0\u6a19\u7c64 -gb.createdThisTicket = \u5df2\u958b\u7acb\u7684\u4efb\u52d9\u55ae -gb.createFirstTicket = \u6309\u6b64\u9996\u767c\u4efb\u52d9\u55ae -gb.createPermission = {0} (push, ref creation) -gb.createReadme = \u5efa\u7acbREADME\u6a94\u6848 +gb.servers = \u4f3a\u670d\u5668 +gb.recent = \u6700\u8fd1 +gb.available = \u53ef\u7528 +gb.selected = \u9078\u5b9a +gb.size = \u5bb9\u91cf +gb.downloading = \u4e0b\u8f09\u4e2d +gb.loading = \u8f09\u5165 +gb.starting = \u555f\u52d5\u4e2d +gb.general = \u4e00\u822c +gb.settings = \u8a2d\u5b9a +gb.manage = \u7ba1\u7406 +gb.lastLogin = \u6700\u8fd1\u767b\u5165 +gb.skipSizeCalculation = \u7565\u904e\u5bb9\u91cf\u8a08\u7b97 +gb.skipSizeCalculationDescription = \u4e0d\u8a08\u7b97\u7248\u672c\u5eab\u5bb9\u91cf(\u52a0\u5feb\u7db2\u9801\u8f09\u5165\u901f\u5ea6) +gb.skipSummaryMetrics = \u7565\u904e\u91cf\u5316\u532f\u7e3d +gb.skipSummaryMetricsDescription = \u4e0d\u8981\u8a08\u7b97\u91cf\u5316\u4e26\u4e14\u986f\u793a\u5728\u532f\u7e3d\u9801\u9762\u4e0a(\u52a0\u5feb\u901f\u5ea6) +gb.accessLevel = \u5b58\u53d6\u7b49\u7d1a +gb.default = \u9810\u8a2d +gb.setDefault = \u8a2d\u70ba\u9810\u8a2d\u503c +gb.since = \u5f9e +gb.bootDate = \u555f\u52d5\u65e5 +gb.servletContainer = servlet\u5bb9\u5668 +gb.heapMaximum = \u6700\u5927\u5806\u7a4d(heap) +gb.heapAllocated = \u5df2\u4f7f\u7528\u5806\u7a4d(Heap) +gb.heapUsed = \u5df2\u4f7f\u7528\u7684\u5806\u7a4d(heap) +gb.free = \u91cb\u653e +gb.version = \u7248\u672c +gb.releaseDate = \u767c\u8868\u65e5 +gb.date = \u65e5\u671f +gb.activity = \u6d3b\u52d5 +gb.subscribe = \u8a02\u95b1 +gb.branch = \u5206\u652f +gb.maxHits = \u6700\u5927\u9ede\u64ca +gb.recentActivity = \u6700\u8fd1\u6d3b\u8e8d\u72c0\u6cc1 +gb.recentActivityStats = \u904e\u53bb{0}\u5929,\u4e00\u5171\u6709{2}\u4eba\u505a\u4e86{1}\u4efd\u63d0\u4ea4 +gb.recentActivityNone = \u904e\u53bb{0}\u5929/\u7121 +gb.dailyActivity = \u6bcf\u65e5\u6d3b\u52d5 +gb.activeRepositories = \u6d3b\u8e8d\u7248\u672c\u5eab +gb.activeAuthors = \u6d3b\u8e8d\u7528\u6236 +gb.commits = \u63d0\u4ea4 +gb.teams = \u5718\u968a +gb.teamName = \u5718\u968a\u540d\u7a31 +gb.teamMembers = \u5718\u968a\u6210\u54e1 +gb.teamMemberships = \u5718\u968a\u6210\u54e1(memberships) +gb.newTeam = \u5efa\u7acb\u5718\u968a +gb.permittedTeams = permitted teams +gb.emptyRepository = \u7a7a\u7684\u7248\u672c\u5eab +gb.repositoryUrl = \u7248\u672c\u5eab url +gb.mailingLists = \u90f5\u4ef6\u540d\u55ae +gb.preReceiveScripts = pre-receive \u8173\u672c +gb.postReceiveScripts = post-receive\u8173\u672c +gb.hookScripts = hook\u7684\u8173\u672c gb.customFields = custom fields gb.customFieldsDescription = custom fields available to Groovy hooks -gb.dailyActivity = \u6bcf\u65e5\u6d3b\u52d5 -gb.dashboard = \u5100\u8868\u677f -gb.date = \u65e5\u671f -gb.default = \u9810\u8a2d -gb.delete = \u522a\u9664 -gb.deletedBranch = deleted branch -gb.deletedTag = \u522a\u9664\u6a19\u7c64 -gb.deleteMilestone = \u522a\u9664\u91cc\u7a0b\u7891"{0}"? -gb.deletePermission = {0} (push, ref creation+deletion) -gb.deleteRepository = \u522a\u9664\u7248\u672c\u5eab"{0}"? -gb.deleteRepositoryDescription = \u7248\u672c\u5eab\u522a\u9664\u5c07\u7121\u6cd5\u9084\u539f -gb.deleteRepositoryHeader = \u522a\u9664\u7248\u672c\u5eab -gb.deleteUser = \u522a\u9664\u4f7f\u7528\u8005"{0}"? -gb.deletion = \u522a\u9664 -gb.description = \u6982\u8ff0 -gb.destinationUrl = \u50b3\u9001 -gb.destinationUrlDescription = \u50b3\u9001Gitblit\u9023\u7d50\u5230\u4f60\u7684\u5c08\u6848(proposal) -gb.diff = \u5dee\u7570 -gb.diffCopiedFile = File was copied from {0} -gb.diffDeletedFile = \u6a94\u6848\u5df2\u522a\u9664 -gb.diffDeletedFileSkipped = (\u522a\u9664) -gb.diffFileDiffTooLarge = \u6a94\u6848\u592a\u5927 -gb.diffNewFile = \u6bd4\u5c0d\u65b0\u6a94\u6848 -gb.diffRenamedFile = File was renamed from {0} -gb.diffStat = \u65b0\u589e{0}\u5217\u8207\u522a\u9664{1}\u5217 -gb.difftocurrent = \u6bd4\u5c0d\u5dee\u7570 -gb.diffTruncated = Diff truncated after the above file -gb.disableUser = \u505c\u7528\u5e33\u6236 -gb.disableUserDescription = \u8a72\u5e33\u6236\u7121\u6cd5\u4f7f\u7528 -gb.discussion = \u8a0e\u8ad6 -gb.displayName = \u986f\u793a\u7684\u540d\u7a31 -gb.displayNameDescription = \u5e0c\u671b\u986f\u793a\u7684\u540d\u7a31 -gb.docs = \u6a94\u6848\u5340 -gb.docsWelcome1 = \u4f60\u53ef\u4ee5\u4f7f\u7528\u6a94\u6848\u5340\u5efa\u7acb\u6587\u4ef6\u5eab\u7684\u6559\u5b78\u6a94\u6848 -gb.docsWelcome2 = \u63d0\u4ea4README.md \u6216 HOME.md\u5f8c,\u518d\u958b\u59cb\u65b0\u7684\u6587\u4ef6\u5eab -gb.doesNotExistInTree = {0}\u4e26\u6c92\u6709\u5728\u76ee\u9304{1}\u88e1\u9762 -gb.download = \u4e0b\u8f09 -gb.downloading = \u4e0b\u8f09ing -gb.due = due -gb.duration = \u9031\u671f -gb.duration.days = {0}\u5929 -gb.duration.months = {0}\u6708 -gb.duration.oneDay = 1\u5929 -gb.duration.oneMonth = 1\u6708 -gb.duration.oneYear = 1\u5e74 -gb.duration.years = {0}\u5e74 -gb.edit = \u7de8\u8f2f -gb.editMilestone = \u4fee\u6539milestone -gb.editTicket = \u4fee\u6539\u4efb\u52d9\u55ae -gb.editUsers = \u4fee\u6539\u5e33\u865f -gb.effective = \u6240\u6709\u6b0a\u9650 +gb.accessPermissions = \u5b58\u53d6\u6b0a\u9650 +gb.filters = \u7be9\u9078 +gb.generalDescription = \u4e00\u822c\u8a2d\u5b9a +gb.accessPermissionsDescription = restrict access by users and teams +gb.accessPermissionsForUserDescription = set team memberships or grant access to specific restricted repositories +gb.accessPermissionsForTeamDescription = set team members and grant access to specific restricted repositories +gb.federationRepositoryDescription = \u8207\u5176\u4ed6gitblit\u4f3a\u670d\u5668\u5206\u4eab\u4e00\u8d77\u4f7f\u7528\u9019\u500b\u7248\u672c\u5eab +gb.hookScriptsDescription = \u7576\u63a8\u9001(push)\u81f3\u6b64Gitblit\u7248\u63a7\u4f3a\u670d\u5668\u6642, \u57f7\u884cGroovy\u8173\u672c +gb.reset = \u6e05\u9664 +gb.pages = \u6587\u4ef6 +gb.workingCopy = \u66ab\u5b58\u8907\u672c +gb.workingCopyWarning = \u8a72\u7248\u672c\u5eab\u4ecd\u6709\u66ab\u5b58\u8907\u672c,\u56e0\u6b64\u7121\u6cd5\u63a5\u53d7\u63a8\u9001(push) +gb.query = \u67e5\u8a62 +gb.queryHelp = \u652f\u63f4\u6a19\u6e96\u67e5\u8a62\u8a9e\u6cd5.

\u8a73\u60c5\u8acb\u53c3\u8003 Lucene Query Parser Syntax +gb.queryResults = \u7d50\u679c {0} - {1} ({2} \u67e5\u8a62) +gb.noHits = \u7121\u9ede\u64ca +gb.authored = \u6388\u6b0a +gb.committed = \u5df2\u63d0\u4ea4 +gb.indexedBranches = \u5206\u652f\u7d22\u5f15 +gb.indexedBranchesDescription = \u9078\u5b9a\u6b32\u57f7\u884cLucene\u7d22\u5f15\u529f\u80fd\u7684\u5206\u652f +gb.noIndexedRepositoriesWarning = \u8ddf\u4f60\u76f8\u95dc\u7684\u7248\u672c\u5eab\u4e26\u6c92\u6709\u505aLucene\u7d22\u5f15 +gb.undefinedQueryWarning = \u672a\u8a2d\u5b9a\u67e5\u8a62\u689d\u4ef6 +gb.noSelectedRepositoriesWarning = \u8acb\u81f3\u5c11\u9078\u64c7\u4e00\u500b\u7248\u672c\u5eab +gb.luceneDisabled = \u505c\u7528Lucene\u7d22\u5f15\u529f\u80fd +gb.failedtoRead = \u8b80\u53d6\u5931\u6557 +gb.isNotValidFile = \u4e0d\u662f\u6709\u6548\u6a94\u6848 +gb.failedToReadMessage = Failed to read default message from {0}\! +gb.passwordsDoNotMatch = \u5bc6\u78bc\u4e0d\u76f8\u7b26 +gb.passwordTooShort = \u5bc6\u78bc\u904e\u77ed, \u6700\u5c11{0}\u500b\u5b57\u5143 +gb.passwordChanged = \u5bc6\u78bc\u8b8a\u66f4\u6210\u529f +gb.passwordChangeAborted = \u53d6\u6d88\u5bc6\u78bc\u8b8a\u66f4 +gb.pleaseSetRepositoryName = \u8acb\u8a2d\u5b9a\u7248\u672c\u5eab\u540d\u7a31 +gb.illegalLeadingSlash = \u7981\u6b62\u6839\u76ee\u9304(/) +gb.illegalRelativeSlash = \u7981\u6b62\u76f8\u5c0d\u76ee\u9304(../) +gb.illegalCharacterRepositoryName = \u7248\u672c\u5eab\u540d\u7a31\u6709\u4e0d\u5408\u6cd5\u7684\u5b57\u5143"{0}" +gb.selectAccessRestriction = Please select access restriction\! +gb.selectFederationStrategy = Please select federation strategy\! +gb.pleaseSetTeamName = \u8acb\u8f38\u5165\u5718\u968a\u540d\u7a31 +gb.teamNameUnavailable = \u5718\u968a"{0}"\u4e0d\u5b58\u5728. +gb.teamMustSpecifyRepository = \u5718\u968a\u6700\u5c11\u8981\u6307\u5b9a\u4e00\u500b\u7248\u672c\u5eab +gb.teamCreated = \u5718\u968a"{0}"\u65b0\u589e\u6210\u529f. +gb.pleaseSetUsername = \u8acb\u8f38\u5165\u4f7f\u7528\u8005\u540d\u7a31 +gb.usernameUnavailable = \u4f7f\u7528\u8005\u540d\u7a31"{0}"\u4e0d\u53ef\u7528 +gb.combinedMd5Rename = Gitblit\u4f7f\u7528md5\u65b9\u5f0f\u5c07\u5bc6\u78bc\u7de8\u78bc(\u7121\u6cd5\u9084\u539f).\u4f60\u5fc5\u9808\u8f38\u5165\u65b0\u5bc6\u78bc. +gb.userCreated = \u6210\u529f\u5efa\u7acb\u65b0\u4f7f\u7528\u8005"{0}" +gb.couldNotFindFederationRegistration = \u627e\u4e0d\u5230federation registration! +gb.failedToFindGravatarProfile = \u7121\u6cd5\u627e\u5230\u5e33\u865f{0}\u7684Gravator\u8cc7\u6599 +gb.branchStats = \u9019\u500b\u5206\u652f{2}\u6709{0}\u500b\u63d0\u4ea4\u4ee5\u53ca{1}\u500b\u6a19\u7c64 +gb.repositoryNotSpecified = \u672a\u6307\u5b9a\u7248\u672c\u5eab! +gb.repositoryNotSpecifiedFor = \u7248\u672c\u5eab\u4e26\u6c92\u6709\u6307\u5b9a\u7d66 {0}\! +gb.canNotLoadRepository = \u7121\u6cd5\u8f09\u5165\u7248\u672c\u5eab +gb.commitIsNull = \u63d0\u4ea4\u5167\u5bb9\u662f\u7a7a\u7684 +gb.unauthorizedAccessForRepository = \u7248\u672c\u5eab\u672a\u6388\u6b0a\u5b58\u53d6 +gb.failedToFindCommit = \u5728{1}\u4e2d\u7121\u6cd5\u627e\u5230\u8a72 {0} \u63d0\u4ea4! +gb.couldNotFindFederationProposal = \u641c\u5c0b\u4e0d\u5230federation proposal! +gb.invalidUsernameOrPassword = \u932f\u8aa4\u7684\u4f7f\u7528\u8005\u540d\u7a31\u6216\u5bc6\u78bc! +gb.OneProposalToReview = \u6709\u4e00\u500bfederation proposal \u7b49\u5f85\u5be9\u67e5 +gb.nFederationProposalsToReview = \u7e3d\u5171\u6709{0}\u500bfederation proposals\u7b49\u5f85\u5be9\u8996 +gb.couldNotFindTag = \u627e\u4e0d\u5230\u6a19\u7c64{0} +gb.couldNotCreateFederationProposal = \u7121\u6cd5\u5efa\u7acbfederation proposals +gb.pleaseSetGitblitUrl = \u8acb\u8f38\u5165Gitblit URL ! +gb.pleaseSetDestinationUrl = Please enter a destination url for your proposal\! +gb.proposalReceived = Proposal successfully received by {0}. +gb.noGitblitFound = Sorry, {0} could not find a Gitblit instance at {1}. +gb.noProposals = \u62b1\u6b49, {0}\u6b64\u6642\u4e26\u4e0d\u662f\u53ef\u63a5\u53d7\u7684proposals. +gb.noFederation = Sorry, {0} is not configured to federate with any Gitblit instances. +gb.proposalFailed = Sorry, {0} did not receive any proposal data\! +gb.proposalError = \u62b1\u6b49, {0} \u4efd\u5831\u544a\u767c\u751f\u9810\u671f\u5916\u7684\u932f\u8aa4! +gb.failedToSendProposal = \u63d0\u6848\u767c\u9001\u5931\u6557\! +gb.userServiceDoesNotPermitAddUser = {0}\u4e0d\u5141\u8a31\u65b0\u589e\u4f7f\u7528\u8005\u5e33\u865f +gb.userServiceDoesNotPermitPasswordChanges = {0}\u4e0d\u5141\u8a31\u4fee\u6539\u5bc6\u78bc +gb.displayName = \u986f\u793a\u7684\u540d\u7a31 gb.emailAddress = \u96fb\u5b50\u90f5\u4ef6 -gb.emailAddressDescription = \u7528\u4f86\u63a5\u6536\u901a\u77e5\u7684\u4e3b\u8981\u96fb\u5b50\u90f5\u4ef6 -gb.emailCertificateBundle = \u5bc4\u767c\u7528\u6236\u7aef\u8b49\u66f8 -gb.emailMeOnMyTicketChanges = \u6211\u7684\u4efb\u52d9\u55ae\u82e5\u6709\u8b8a\u66f4,\u8acb800\u91cc\u52a0\u6025(email)\u901a\u77e5\u6211 -gb.emailMeOnMyTicketChangesDescription = \u6211\u8655\u7406\u904e\u7684\u4efb\u52d9\u55ae\u8acbemail\u901a\u77e5\u6211 -gb.empty = \u7a7a\u7684 -gb.emptyRepository = \u7a7a\u7684\u7248\u672c\u5eab -gb.enableDocs = \u555f\u7528\u6a94\u6848\u5340 -gb.enableIncrementalPushTags = \u555f\u7528\u81ea\u52d5\u65b0\u589e\u6a19\u7c64\u529f\u80fd -gb.enableTickets = \u555f\u7528\u4efb\u52d9\u55ae\u7cfb\u7d71 -gb.enhancementTickets = \u512a\u5316 -gb.enterKeystorePassword = \u8acb\u8f38\u5165Gitblit\u7684keystore\u5c08\u7528\u5bc6\u78bc -gb.error = \u932f\u8aa4 -gb.errorAdministrationDisabled = \u7ba1\u7406\u6b0a\u9650\u5df2\u53d6\u6d88 gb.errorAdminLoginRequired = \u767b\u5165\u9700\u6709\u7ba1\u7406\u6b0a\u9650 gb.errorOnlyAdminMayCreateRepository = \u53ea\u6709\u7ba1\u7406\u8005\u80fd\u5efa\u7acb\u7248\u672c\u5eab gb.errorOnlyAdminOrOwnerMayEditRepository = \u53ea\u6709\u7ba1\u7406\u8005\u8207\u7248\u672c\u5eab\u64c1\u6709\u8005\u80fd\u4fee\u6539\u7248\u672c\u5eab\u5c6c\u6027 -gb.excludeFromActivity = exclude from activity page -gb.excludeFromFederation = \u6392\u9664\u4e32\u9023 -gb.excludeFromFederationDescription = \u963b\u64cb\u5df2\u4e32\u9023\u7684Gitblit\u4f3a\u670d\u5668 -gb.excludePermission = {0} (\u6392\u9664) -gb.exclusions = \u6392\u9664 -gb.expired = \u904e\u671f -gb.expires = \u5230\u671f -gb.expiring = \u5c07\u8981\u904e\u671f -gb.export = \u532f\u51fa -gb.extensions = \u64f4\u5145 -gb.externalPermissions = {0} access permissions are externally maintained -gb.failedToFindAccount = \u7121\u6cd5\u641c\u5c0b\u5230\u5e33\u865f"{0}" -gb.failedToFindCommit = Failed to find commit "{0}" in {1}\! -gb.failedToFindGravatarProfile = \u7121\u6cd5\u627e\u5230\u5e33\u865f{0}\u7684Gravator\u8cc7\u6599 -gb.failedtoRead = \u8b80\u53d6\u5931\u6557 -gb.failedToReadMessage = Failed to read default message from {0}\! -gb.failedToSendProposal = \u63d0\u6848\u767c\u9001\u5931\u6557\! -gb.failedToUpdateUser = \u7121\u6cd5\u66f4\u65b0\u4f7f\u7528\u8005\u5e33\u865f -gb.federatedRepositoryDefinitions = \u7248\u672c\u5eab\u5b9a\u7fa9 -gb.federatedSettingDefinitions = setting definitions -gb.federatedUserDefinitions = user definitions -gb.federateOrigin = federate the origin -gb.federateThis = \u8207\u672c\u6587\u4ef6\u5eab\u4e32\u9023 -gb.federation = \u4e32\u9023 -gb.federationRegistration = federation registration -gb.federationRepositoryDescription = \u8207\u5176\u4ed6gitblit\u4f3a\u670d\u5668\u5206\u4eab\u4e00\u8d77\u4f7f\u7528\u9019\u500b\u7248\u672c\u5eab -gb.federationResults = federation pull results -gb.federationSets = \u4e32\u9023\u7d44\u5408 -gb.federationSetsDescription = \u6b64\u6587\u4ef6\u5eab\u5c07\u5305\u542b\u65bc\u6307\u5b9a\u7684\u4e32\u9023\u7fa4\u7d44(federation sets) -gb.federationStrategy = \u4e32\u9023\u7b56\u7565 -gb.federationStrategyDescription = \u63a7\u5236\u5982\u4f55\u5c07\u6587\u4ef6\u5eab\u8207\u5176\u4ed6Gitblit\u7248\u63a7\u4f3a\u670d\u5668\u4e32\u9023 -gb.feed = \u8cc7\u6599\u8a02\u95b1 -gb.filesAdded = \u65b0\u589e{0}\u500b\u6a94\u6848 -gb.filesCopied = \u8907\u88fd{0}\u500b\u6a94\u6848 -gb.filesDeleted = \u522a\u9664{0}\u500b\u6a94\u6848 -gb.filesModified = \u4fee\u6539{0}\u500b\u6a94\u6848 -gb.filesRenamed = \u4fee\u6539{0}\u500b\u6a94\u6848\u540d\u7a31 -gb.filter = \u689d\u4ef6\u904e\u6ffe -gb.filters = \u67e5\u8a62\u689d\u4ef6 -gb.findSomeRepositories = \u641c\u5c0b\u6587\u4ef6\u5eab -gb.folder = \u76ee\u9304 +gb.errorAdministrationDisabled = \u7ba1\u7406\u6b0a\u9650\u5df2\u53d6\u6d88 +gb.lastNDays = \u6700\u8fd1{0}\u5929 +gb.completeGravatarProfile = \u5b8c\u6210Gravator.com\u4e0a\u7684\u57fa\u672c\u8cc7\u6599\u8a2d\u5b9a +gb.none = \u7121 +gb.line = \u884c +gb.content = \u5167\u5bb9 +gb.empty = \u7a7a\u7684 +gb.inherited = \u7e7c\u627f +gb.deleteRepository = \u522a\u9664\u7248\u672c\u5eab"{0}"? +gb.repositoryDeleted = \u7248\u672c\u5eab"{0}"\u5df2\u522a\u9664 +gb.repositoryDeleteFailed = \u522a\u9664\u7248\u672c\u5eab"{0}"\u5931\u6557! +gb.deleteUser = \u522a\u9664\u4f7f\u7528\u8005"{0}"? +gb.userDeleted = \u4f7f\u7528\u8005"{0}"\u5df2\u522a\u9664 +gb.userDeleteFailed = \u4f7f\u7528\u8005"{0}"\u522a\u9664\u5931\u6557 +gb.time.justNow = \u525b\u525b +gb.time.today = \u4eca\u5929 +gb.time.yesterday = \u6628\u5929 +gb.time.minsAgo = {0}\u5206\u9418\u524d +gb.time.hoursAgo = {0}\u5c0f\u6642\u524d +gb.time.daysAgo = {0}\u5929\u524d +gb.time.weeksAgo = {0}\u5468\u524d +gb.time.monthsAgo = {0}\u6708\u524d +gb.time.oneYearAgo = 1\u5e74\u524d +gb.time.yearsAgo = {0}\u5e74\u524d +gb.duration.oneDay = 1\u5929 +gb.duration.days = {0}\u5929 +gb.duration.oneMonth = 1\u6708 +gb.duration.months = {0}\u6708 +gb.duration.oneYear = 1\u5e74 +gb.duration.years = {0}\u5e74 +gb.authorizationControl = \u6388\u6b0a\u7ba1\u63a7 +gb.allowAuthenticatedDescription = \u6279\u51c6 RW+ \u6b0a\u9650\u7d66\u4e88\u5c08\u6848\u6210\u54e1 +gb.allowNamedDescription = grant fine-grained permissions to named users or teams +gb.markdownFailure = \u89e3\u6790Markdown\u5931\u6557 +gb.clearCache = \u6e05\u9664\u5feb\u53d6 +gb.projects = \u7fa4\u7d44 +gb.project = \u7fa4\u7d44 +gb.allProjects = \u5168\u90e8\u7fa4\u7d44 +gb.copyToClipboard = \u8907\u88fd\u5230\u526a\u8cbc\u677f gb.fork = \u5efa\u7acb\u5206\u652f(fork) -gb.forkedFrom = forked from -gb.forkInProgress = fork in progress -gb.forkNotAuthorized = \u5f88\u62b1\u6b49, \u4f60\u7121\u5efa\u7acb\u6587\u4ef6\u5eab{0}\u5206\u652f(fork)\u7684\u6b0a\u9650 -gb.forkRepository = \u7248\u672c\u5eab{0}\u5efa\u7acb\u5206\u652f(fork)? gb.forks = \u5206\u652f(forks) +gb.forkRepository = \u7248\u672c\u5eab{0}\u5efa\u7acb\u5206\u652f(fork)? +gb.repositoryForked = \u7248\u672c\u5eab{0}\u5df2\u7d93\u5efa\u7acb\u5206\u652f(fork) +gb.repositoryForkFailed = +gb.personalRepositories = \u500b\u4eba\u7248\u672c\u5eab +gb.allowForks = \u5141\u8a31\u5efa\u7acb\u5206\u652f(forks) +gb.allowForksDescription = \u5141\u8a31\u5df2\u6388\u6b0a\u7684\u4f7f\u7528\u8005\u5f9e\u7248\u672c\u5eab\u5efa\u7acb\u5206\u652f(fork) +gb.forkedFrom = \u6e90\u81ea\u65bc +gb.canFork = \u53ef\u5efa\u7acb\u5206\u652f(fork) +gb.canForkDescription = \u53ef\u4ee5\u5efa\u7acb\u7248\u672c\u5eab\u5206\u652f(fork),\u4e26\u4e14\u8907\u88fd\u5230\u79c1\u4eba\u7248\u672c\u5eab\u4e2d +gb.myFork = \u6aa2\u8996\u6211\u5efa\u7acb\u7684\u5206\u652f(fork) gb.forksProhibited = \u7981\u6b62\u5efa\u7acb\u5206\u652f(forks) -gb.forksProhibitedWarning = \u672c\u6587\u4ef6\u5eab\u7981\u6b62\u5206\u652f(fork) -gb.free = \u91cb\u653e -gb.frequency = \u983b\u7387 -gb.from = from -gb.garbageCollection = \u56de\u6536\u7cfb\u7d71\u8cc7\u6e90 -gb.garbageCollectionDescription = \u7cfb\u7d71\u8cc7\u6e90\u56de\u6536\u529f\u80fd\u5c07\u6703\u6574\u9813\u9b06\u6563\u7528\u6236\u7aef\u63a8\u9001(push)\u7684\u7269\u4ef6, \u4e5f\u6703\u79fb\u9664\u6587\u4ef6\u5eab\u4e0a\u7121\u7528\u7684\u7269\u4ef6 -gb.gc = \u7cfb\u7d71\u8cc7\u6e90\u56de\u6536\u5668 +gb.forksProhibitedWarning = \u672c\u7248\u672c\u5eab\u7981\u6b62\u5206\u652f(fork) +gb.noForks = {0}\u6c92\u6709\u5206\u652f(fork) +gb.forkNotAuthorized = \u5f88\u62b1\u6b49, \u4f60\u7121\u5efa\u7acb\u7248\u672c\u5eab{0}\u5206\u652f(fork)\u7684\u6b0a\u9650 +gb.forkInProgress = \u6b63\u5728\u8907\u88fd\u4e2d(fork) +gb.preparingFork = \u6b63\u5728\u6e96\u5099\u8907\u88fd\u4e2d(fork)... +gb.isFork = \u662f\u5206\u652f\u985e\u578b(fork) +gb.canCreate = \u53ef\u5efa\u7acb +gb.canCreateDescription = \u80fd\u5920\u5efa\u7acb\u500b\u4eba\u7248\u672c\u5eab +gb.illegalPersonalRepositoryLocation = \u4f60\u500b\u4eba\u7248\u672c\u5eab\u5fc5\u9808\u653e\u5728"{0}" +gb.verifyCommitter = \u63d0\u4ea4\u8005\u9700\u9a57\u8b49 +gb.verifyCommitterDescription = \u9700\u8981\u63d0\u4ea4\u8005\u7b26\u5408\u63a8\u9001\u5e33\u865f +gb.verifyCommitterNote = \u6240\u6709\u5408\u4f75\u52d5\u4f5c\u7686\u9808\u5f37\u5236\u4f7f\u7528"--no-ff"\u53c3\u6578 +gb.repositoryPermissions = \u7248\u672c\u5eab\u6b0a\u9650 +gb.userPermissions = \u4f7f\u7528\u8005\u6b0a\u9650 +gb.teamPermissions = \u5718\u968a\u6b0a\u9650 +gb.add = \u65b0\u589e +gb.noPermission = \u522a\u9664\u9019\u500b\u6b0a\u9650 +gb.excludePermission = {0} \u6392\u9664(exclude) +gb.viewPermission = {0} \u6aa2\u8996(view) +gb.clonePermission = {0} \u8907\u88fd(clone) +gb.pushPermission = {0}(\u63a8\u9001) +gb.createPermission = {0} (push, ref creation) +gb.deletePermission = {0} (push, ref creation+deletion) +gb.rewindPermission = {0} (push, ref creation+deletion+rewind) +gb.permission = \u6b0a\u9650 +gb.regexPermission = \u5df2\u7d93\u4f7f\u7528\u6b63\u898f\u8868\u793a\u5f0f(regular expression)"{0}" \u8a2d\u5b9a\u6b0a\u9650\u5b8c\u7562 +gb.accessDenied = \u62d2\u7d55\u5b58\u53d6 +gb.busyCollectingGarbage = \u62b1\u6b49,Gitblit\u6b63\u5728\u56de\u6536\u7cfb\u7d71\u8cc7\u6e90\u4e2d:{0} gb.gcPeriod = \u7cfb\u7d71\u8cc7\u6e90\u56de\u6536\u968e\u6bb5 gb.gcPeriodDescription = \u56de\u6536\u9031\u671f gb.gcThreshold = GC \u57fa\u6578(threshold) gb.gcThresholdDescription = \u89f8\u767c\u7cfb\u7d71\u8cc7\u6e90\u56de\u6536\u7684\u6700\u5c0f\u7269\u4ef6\u5bb9\u91cf -gb.general = \u4e00\u822c -gb.generalDescription = \u4e00\u822c\u8a2d\u5b9a -gb.hasNotReviewed = \u5c1a\u672a\u6aa2\u6838\u904e -gb.head = HEAD -gb.headRef = \u9810\u8a2d\u5206\u652f(HEAD) -gb.headRefDescription = \u9810\u8a2d\u5206\u652f\u5c07\u6703\u8907\u88fd\u4ee5\u53ca\u986f\u793a\u5230\u532f\u7e3d\u9801\u9762 -gb.heapAllocated = \u5df2\u4f7f\u7528\u5806\u7a4d(Heap) -gb.heapMaximum = \u6700\u5927\u5806\u7a4d(heap) -gb.heapUsed = \u5df2\u4f7f\u7528\u7684\u5806\u7a4d(heap) -gb.history = \u6b77\u7a0b -gb.home = \u9996\u9801 -gb.hookScripts = hook\u7684\u8173\u672c -gb.hookScriptsDescription = \u7576\u63a8\u9001(push)\u81f3\u6b64Gitblit\u7248\u63a7\u4f3a\u670d\u5668\u6642, \u57f7\u884cGroovy\u8173\u672c -gb.hostname = \u4e3b\u6a5f\u540d\u7a31 -gb.hostnameRequired = \u8acb\u8f38\u5165\u4e3b\u6a5f\u540d\u7a31 -gb.ignore_whitespace =\u5ffd\u7565\u7a7a\u767d -gb.illegalCharacterRepositoryName = \u7248\u672c\u5eab\u540d\u7a31\u6709\u4e0d\u5408\u6cd5\u7684\u5b57\u5143"{0}" -gb.illegalLeadingSlash = \u7981\u6b62\u6839\u76ee\u9304(/) -gb.illegalPersonalRepositoryLocation = \u4f60\u79c1\u4eba\u7248\u672c\u5eab\u5fc5\u9808\u653e\u5728"{0}" -gb.illegalRelativeSlash = \u7981\u6b62\u76f8\u5c0d\u76ee\u9304(../) -gb.imgdiffSubtract = Subtract (black = identical) -gb.in = in -gb.inclusions = inclusions -gb.incrementalPushTagMessage = \u7576[{0}]\u5206\u652f\u63a8\u9001\u5f8c,\u81ea\u52d5\u7d66\u4e88\u6a19\u7c64\u865f. -gb.indexedBranches = \u5206\u652f\u7d22\u5f15 -gb.indexedBranchesDescription = \u9078\u5b9a\u6b32\u57f7\u884cLucene\u7d22\u5f15\u529f\u80fd\u7684\u5206\u652f -gb.inherited = \u7e7c\u627f -gb.initialCommit = \u521d\u6b21\u63d0\u4ea4 -gb.initialCommitDescription = \u4ee5\u4e0b\u6b65\u9a5f\u5c07\u6703\u8b93\u4f60\u99ac\u4e0a\u57f7\u884cgit clone.\u5982\u679c\u4f60\u672c\u6a5f\u5df2\u6709\u6b64\u6587\u4ef6\u5eab\u4e14\u57f7\u884c\u904egit init,\u8acb\u8df3\u904e\u6b64\u6b65\u9a5f. -gb.initWithGitignore = \u5305\u542b .gitignore \u6a94\u6848 -gb.initWithGitignoreDescription = \u65b0\u589e\u4e00\u500b\u8a2d\u5b9a\u6a94\u7528\u4f86\u6307\u5b9a\u54ea\u4e9b\u6a94\u6848\u6216\u76ee\u9304\u9700\u8981\u5ffd\u7565 -gb.initWithReadme = \u5305\u542bREADME\u6587\u4ef6 -gb.initWithReadmeDescription = \u6587\u4ef6\u5eab\u5c07\u7522\u751f\u7c21\u55aeREADME\u6587\u4ef6 -gb.invalidExpirationDate = \u4e0d\u6b63\u78ba\u7684\u5230\u671f\u65e5 -gb.invalidUsernameOrPassword = \u932f\u8aa4\u7684\u4f7f\u7528\u8005\u540d\u7a31\u6216\u5bc6\u78bc! -gb.isFederated = \u5df2\u7d93\u4e32\u9023 -gb.isFork = \u662f\u5206\u652f\u985e\u578b(fork) -gb.isFrozen = \u51cd\u7d50\u63a5\u6536 -gb.isFrozenDescription = \u7981\u6b62\u63a8\u9001(push) -gb.isMirror = \u8a72\u6587\u4ef6\u5eab\u70ba\u93e1\u50cf(mirror) -gb.isNotValidFile = \u4e0d\u662f\u6b63\u5e38\u6a94\u6848 -gb.isSparkleshared = \u8a72\u6587\u4ef6\u5eab\u5df2\u70baSparkleshared (http://sparkleshare.org) -gb.issued = \u767c\u51fa -gb.issuer = issuer -gb.jceWarning = Your Java Runtime Environment does not have the "JCE Unlimited Strength Jurisdiction Policy" files.\nThis will limit the length of passwords you may use to encrypt your keystores to 7 characters.\nThese policy files are an optional download from Oracle.\n\nWould you like to continue and generate the certificate infrastructure anyway?\n\nAnswering No will direct your browser to Oracle's download page so that you may download the policy files. -gb.key = \u91d1\u9470 -gb.keyCompromise = \u91d1\u9470\u5bc6\u78bc\u5916\u6d29 -gb.labels = \u6a19\u8a18 -gb.languagePreference = \u5e38\u7528\u8a9e\u8a00 -gb.languagePreferenceDescription = \u9078\u64c7\u4f60\u60f3\u8981\u7684Gitblit\u7ffb\u8b6f -gb.lastChange = \u6700\u8fd1\u4fee\u6539 -gb.lastLogin = \u6700\u8fd1\u767b\u5165 -gb.lastNDays = \u6700\u8fd1{0}\u5929 -gb.lastPull = \u4e0a\u6b21\u4e0b\u8f09(pull) -gb.leaveComment = \u7559\u4e0b\u8a3b\u89e3 -gb.line = \u884c -gb.loading = \u8f09\u5165 -gb.local = \u672c\u5730\u7aef -gb.locality = \u4f4d\u7f6e -gb.log = \u65e5\u8a8c -gb.login = \u767b\u5165 -gb.logout = \u767b\u51fa -gb.looksGood = \u770b\u8d77\u4f86\u5f88\u597d -gb.luceneDisabled = \u505c\u7528Lucene\u7d22\u5f15\u529f\u80fd -gb.mailingLists = \u90f5\u4ef6\u540d\u55ae -gb.maintenanceTickets = \u7dad\u8b77 -gb.manage = \u7ba1\u7406 -gb.manual = \u81ea\u884c\u8f38\u5165 -gb.markdown = markdown -gb.markdownFailure = \u89e3\u6790Markdown\u5931\u6557 -gb.maxActivityCommits = \u6700\u5927\u63d0\u4ea4\u6d3b\u8e8d\u7387 -gb.maxActivityCommitsDescription = \u6700\u5927\u63d0\u4ea4\u6d3b\u8e8d\u6578\u91cf -gb.maxHits = \u6700\u5927\u9ede\u64ca -gb.md5FingerPrint = MD5 Fingerprint -gb.mentions = \u63d0\u5230 -gb.mentionsMeTickets = \u63d0\u5230\u4f60 -gb.merge = \u5408\u4f75 -gb.mergeBase = \u57fa\u672c\u5408\u4f75 -gb.merged = \u5df2\u5408\u4f75 -gb.mergedPatchset = \u5c07\u88dc\u4e01\u5408\u4f75 -gb.mergedPullRequest = \u5408\u4f75\u63a8\u9001\u8981\u6c42 -gb.mergeSha = mergeSha -gb.mergeStep1 = Check out a new branch to review the changes \u2014 run this from your project directory -gb.mergeStep2 = Bring in the proposed changes and review -gb.mergeStep3 = \u5c07\u63d0\u6848\u4fee\u6539\u5167\u5bb9\u5408\u4f75\u5230\u4f3a\u670d\u5668\u4e0a -gb.mergeTo = \u5408\u4f75\u5230 -gb.mergeToDescription = \u9810\u8a2d\u5c07\u6587\u4ef6\u76f8\u95dc\u88dc\u4e01\u5305\u8207\u6307\u5b9a\u5206\u652f(branch)\u5408\u4f75 -gb.mergingViaCommandLine = \u7d93\u7531\u6307\u4ee4\u57f7\u884c\u5408\u4f75 -gb.mergingViaCommandLineNote = \u5982\u679c\u4f60\u4e0d\u60f3\u8981\u4f7f\u7528\u81ea\u52d5\u5408\u4f75\u529f\u80fd,\u6216\u662f\u6309\u4e0b\u5408\u4f75\u6309\u9215, \u4f60\u53ef\u4ee5\u4e0b\u6307\u4ee4\u624b\u52d5\u5408\u4f75 -gb.message = \u8a0a\u606f -gb.metricAuthorExclusions = \u91cf\u5316\u7d71\u8a08\u6642\u6392\u9664\u6d3b\u8e8d\u5e33\u6236 -gb.metrics = \u91cf\u5316\u7d71\u8a08 -gb.milestone = \u91cc\u7a0b\u7891 -gb.milestoneDeleteFailed = \u522a\u9664\u91cc\u7a0b\u7891"{0}"\u5931\u6557 -gb.milestoneProgress = {0}\u958b\u555f,{1}\u7d50\u675f -gb.milestones = \u91cc\u7a0b\u7891 -gb.mirrorOf = {0}\u7684\u93e1\u50cf -gb.mirrorWarning = \u8a72\u6587\u4ef6\u5eab\u5c6c\u65bc\u93e1\u50cf, \u4e0d\u80fd\u5920\u63a5\u6536\u63a8\u9001(push) -gb.miscellaneous = \u5176\u4ed6 +gb.ownerPermission = \u7248\u672c\u5eab\u64c1\u6709\u8005 +gb.administrator = \u7ba1\u7406\u54e1 +gb.administratorPermission = Gitblit \u7ba1\u7406\u54e1 +gb.team = \u5718\u968a +gb.teamPermission = "{0}" \u5718\u968a\u6210\u54e1\u7684\u6b0a\u9650 gb.missing = \u5931\u8aa4! -gb.missingIntegrationBranchMore = \u76ee\u6a19\u5206\u652f\u4e0d\u5728\u6b64\u7248\u672c\u5eab -gb.missingPermission = the repository for this permission is missing\! -gb.missingUsername = \u7f3a\u5c11\u4f7f\u7528\u8005\u540d\u7a31 -gb.modification = \u4fee\u6539 -gb.monthlyActivity = \u6708\u6d3b\u52d5 -gb.moreChanges = \u6240\u6709\u8b8a\u66f4... -gb.moreHistory = \u66f4\u591a\u6b77\u53f2\u7d00\u9304... -gb.moreLogs = \u66f4\u591a\u63d0\u4ea4 ... +gb.missingPermission = \u8a72\u6b0a\u9650\u7121\u6cd5\u5c0d\u61c9\u5230\u7248\u672c\u5eab! gb.mutable = \u52d5\u614b\u7d66\u4e88 -gb.myDashboard = \u6211\u7684\u5100\u8868\u677f -gb.myFork = \u6aa2\u8996\u6211\u5efa\u7acb\u7684\u5206\u652f(fork) -gb.myProfile = \u6211\u7684\u57fa\u672c\u8cc7\u6599 -gb.myRepositories = \u6211\u7684\u7248\u672c\u5eab -gb.myTickets = \u6211\u7684\u4efb\u52d9\u55ae -gb.myUrlDescription = \u4f60Gitblit\u4f3a\u670d\u5668\u7684\u516c\u958bURL -gb.name = \u540d\u5b57 -gb.nameDescription = \u4f7f\u7528"/"\u505a\u70ba\u6587\u4ef6\u5eab\u7fa4\u7d44\u5206\u985e. \u5982: library/mycoolib.git -gb.namedPushPolicy = Restrict Push (Named) -gb.namedPushPolicyDescription = \u4efb\u4f55\u4eba\u7686\u53ef\u6aa2\u8996\u8207\u8907\u88fd(clone)\u6587\u4ef6\u5eab. \u4f60\u53ef\u53e6\u5916\u6307\u5b9a\u8ab0\u80fd\u5920\u6709\u63a8\u9001\u529f\u80fd(push) -gb.nAttachments = {0}\u500b\u9644\u4ef6 -gb.nClosedTickets = {0}\u9805\u7d50\u675f -gb.nComments = {0}\u500b\u8a3b\u89e3 -gb.nCommits = {0}\u4efd\u63d0\u4ea4 -gb.needsImprovement = \u9700\u8981\u512a\u5316 -gb.new = \u5efa\u7acb +gb.specified = \u6307\u5b9a\u7d66\u4e88(\u542b\u7cfb\u7d71\u9810\u8a2d) +gb.effective = \u6240\u6709\u6b0a\u9650 +gb.organizationalUnit = \u7d44\u7e54\u55ae\u4f4d +gb.organization = \u7d44\u7e54 +gb.locality = \u4f4d\u7f6e +gb.stateProvince = \u5dde\u6216\u7701 +gb.countryCode = \u570b\u5bb6\u4ee3\u78bc +gb.properties = \u5c6c\u6027 +gb.issued = \u767c\u51fa +gb.expires = \u5230\u671f +gb.expired = \u904e\u671f +gb.expiring = \u5c07\u8981\u904e\u671f +gb.revoked = \u5df2\u64a4\u92b7 +gb.serialNumber = \u5e8f\u865f +gb.certificates = \u8b49\u66f8 gb.newCertificate = \u5efa\u7acb\u8b49\u66f8 +gb.revokeCertificate = \u64a4\u56de\u8b49\u66f8 +gb.sendEmail = \u767cemail +gb.passwordHint = \u5bc6\u78bc\u63d0\u793a +gb.ok = ok +gb.invalidExpirationDate = \u4e0d\u6b63\u78ba\u7684\u5230\u671f\u65e5 +gb.passwordHintRequired = \u5bc6\u78bc\u63d0\u793a(\u5fc5\u8981) +gb.viewCertificate = \u6aa2\u8996\u8b49\u66f8 +gb.subject = \u6a19\u984c +gb.issuer = \u767c\u884c\u8005 +gb.validFrom = \u6709\u6548\u671f\u5f9e +gb.validUntil = \u6709\u6548\u671f\u81f3 +gb.publicKey = \u516c\u958b\u91d1\u9470 +gb.signatureAlgorithm = \u7c3d\u7ae0\u6f14\u7b97\u6cd5 +gb.sha1FingerPrint = SHA-1 Fingerprint +gb.md5FingerPrint = MD5 Fingerprint +gb.reason = \u539f\u56e0 +gb.revokeCertificateReason = \u8acb\u8f38\u5165\u64a4\u56de\u8b49\u66f8\u7406\u7531 +gb.unspecified = \u672a\u6307\u5b9a +gb.keyCompromise = \u91d1\u9470\u5bc6\u78bc\u5916\u6d29 +gb.caCompromise = CA compromise +gb.affiliationChanged = affiliation changed +gb.superseded = \u5df2\u88ab\u66ff\u4ee3 +gb.cessationOfOperation = cessation of operation +gb.privilegeWithdrawn = \u53d6\u6d88\u6b0a\u9650 +gb.time.inMinutes = {0}\u5206\u9418\u5167 +gb.time.inHours = {0}\u5c0f\u6642\u5167 +gb.time.inDays = {0}\u5929\u5167 +gb.hostname = \u4e3b\u6a5f\u540d\u7a31 +gb.hostnameRequired = \u8acb\u8f38\u5165\u4e3b\u6a5f\u540d\u7a31 +gb.newSSLCertificate = \u65b0\u7684\u4f3a\u670d\u5668SSL\u8b49\u66f8 gb.newCertificateDefaults = \u65b0\u8b49\u66f8\u9810\u8a2d\u503c +gb.duration = \u9031\u671f +gb.certificateRevoked = \u8b49\u66f8{0,number,0} \u5df2\u7d93\u88ab\u53d6\u6d88 +gb.clientCertificateGenerated = \u6210\u529f\u7522\u751f{0}\u7684\u65b0\u8b49\u66f8 +gb.sslCertificateGenerated = \u6210\u529f\u7522\u751f\u7d66{0}\u7684\u670d\u5668SSL\u8b49\u66f8 gb.newClientCertificateMessage = \u6ce8\u610f:\n'password'\u5bc6\u78bc\u4e26\u4e0d\u662f\u4f7f\u7528\u8005\u5bc6\u78bc, \u800c\u662f\u7528\u4f86\u4fdd\u8b77\u4f7f\u7528\u8005\u500b\u4eba\u7684keystore.\u8a72\u5bc6\u78bc\u4e26\u4e0d\u6703\u5132\u5b58, \u56e0\u6b64\u5fc5\u9808\u8a2d\u5b9a\u63d0\u793a(hint), \u8a72\u63d0\u793a\u5c07\u6703\u5beb\u5728\u4f7f\u7528\u8005\u7684README\u6587\u4ef6\u88e1\u9762. -gb.newMilestone = \u5efa\u7acb\u91cc\u7a0b\u7891 -gb.newRepository = \u5efa\u7acb\u7248\u672c\u5eab -gb.newSSLCertificate = \u65b0\u7684\u4f3a\u670d\u5668SSL\u8b49\u66f8 -gb.newTeam = \u5efa\u7acb\u5718\u968a -gb.newTicket = \u65b0\u589e\u4efb\u52d9\u55ae -gb.newUser = \u5efa\u7acb\u4f7f\u7528\u8005 -gb.nextPull = next pull -gb.nFederationProposalsToReview = \u7e3d\u5171\u6709{0}\u500b\u4e32\u9023\u8a08\u756b\u7b49\u5f85\u5be9\u8996 +gb.certificate = \u8b49\u66f8 +gb.emailCertificateBundle = \u5bc4\u767c\u7528\u6236\u7aef\u8b49\u66f8 +gb.pleaseGenerateClientCertificate = \u8acb\u7522\u751f\u7d66{0}\u4f7f\u7528\u7684\u7528\u6236\u7aef\u8b49\u66f8 +gb.clientCertificateBundleSent = {0}\u7684\u7528\u6236\u8b49\u66f8\u5df2\u5bc4\u767c +gb.enterKeystorePassword = \u8acb\u8f38\u5165Gitblit\u7684keystore\u5c08\u7528\u5bc6\u78bc +gb.warning = \u8b66\u544a +gb.jceWarning = Your Java Runtime Environment does not have the "JCE Unlimited Strength Jurisdiction Policy" files.\nThis will limit the length of passwords you may use to encrypt your keystores to 7 characters.\nThese policy files are an optional download from Oracle.\n\nWould you like to continue and generate the certificate infrastructure anyway?\n\nAnswering No will direct your browser to Oracle's download page so that you may download the policy files. +gb.maxActivityCommits = \u6700\u5927\u63d0\u4ea4\u6d3b\u8e8d\u7387 +gb.maxActivityCommitsDescription = \u6700\u5927\u63d0\u4ea4\u6d3b\u8e8d\u6578\u91cf +gb.noMaximum = \u7121\u6700\u5927\u503c +gb.attributes = \u5c6c\u6027 +gb.serveCertificate = \u555f\u7528\u4f7f\u7528\u6b64\u8b49\u66f8\u7684https\u529f\u80fd +gb.sslCertificateGeneratedRestart = \u6210\u529f\u7522\u751f\u7d66{0}\u4f7f\u7528\u7684SSL\u8b49\u66f8\n\u4f60\u5fc5\u9808\u91cd\u65b0\u555f\u52d5Gitblit\u7248\u63a7\u4f3a\u670d\u5668\u624d\u80fd\u555f\u7528\u65b0\u7684\u8b49\u66f8\n\nf you are launching with the '--alias' parameter you will have to set that to ''--alias {0}''. +gb.validity = validity +gb.siteName = \u7db2\u7ad9\u540d\u7a31 +gb.siteNameDescription = \u4f3a\u670d\u5668\u7c21\u7a31 +gb.excludeFromActivity = exclude from activity page +gb.isSparkleshared = \u8a72\u7248\u672c\u5eab\u5df2\u70baSparkleshared (http://sparkleshare.org) +gb.owners = \u64c1\u6709\u8005 +gb.sessionEnded = session\u5df2\u7d93\u53d6\u6d88 +gb.closeBrowser = \u8acb\u95dc\u9589\u700f\u89bd\u5668\u7d50\u675f\u6b64\u767b\u5165\u968e\u6bb5 +gb.doesNotExistInTree = {0}\u4e26\u6c92\u6709\u5728\u76ee\u9304{1}\u88e1\u9762 +gb.enableIncrementalPushTags = \u555f\u7528\u81ea\u52d5\u65b0\u589e\u6a19\u7c64\u529f\u80fd +gb.useIncrementalPushTagsDescription = \u63a8\u9001\u6642\u5c07\u81ea\u52d5\u65b0\u589e\u6a19\u7c64\u865f\u78bc +gb.incrementalPushTagMessage = \u7576[{0}]\u5206\u652f\u63a8\u9001\u5f8c,\u81ea\u52d5\u7d66\u4e88\u6a19\u7c64\u865f. +gb.externalPermissions = {0} access permissions are externally maintained +gb.viewAccess = \u4f60\u6c92\u6709Gitblit\u8b80\u53d6\u6216\u662f\u4fee\u6539\u6b0a\u9650 +gb.overview = \u6982\u89c0 +gb.dashboard = \u5100\u8868\u677f +gb.monthlyActivity = \u6708\u6d3b\u52d5 +gb.myProfile = \u6211\u7684\u57fa\u672c\u8cc7\u6599 +gb.compare = \u6bd4\u5c0d +gb.manual = \u81ea\u884c\u8f38\u5165 +gb.from = from +gb.to = to +gb.at = at +gb.of = \u7684 +gb.in = in +gb.moreChanges = \u6240\u6709\u8b8a\u66f4... +gb.pushedNCommitsTo = {0}\u500b\u63d0\u4ea4\u5df2\u63a8\u9001\u81f3 +gb.pushedOneCommitTo = 1\u500b\u63d0\u4ea4\u5df2\u63a8\u9001\u81f3 +gb.commitsTo = {0} \u63d0\u4ea4\u5230\u5206\u652f +gb.oneCommitTo = 1\u500b\u63d0\u4ea4\u5230\u5206\u652f +gb.byNAuthors = \u7d93\u7531{0}\u500b\u4f5c\u8005 +gb.byOneAuthor = \u7d93\u7531{0} +gb.viewComparison = \u6bd4\u8f03\u9019{0}\u500b\u63d0\u4ea4 \u00bb gb.nMoreCommits = \u9084\u6709{0}\u4efd\u63d0\u4ea4 \u00bb +gb.oneMoreCommit = \u9084\u6709\u4e00\u500b\u63d0\u4ea4 \u00bb +gb.pushedNewTag = \u65b0\u6a19\u7c64\u5df2\u63a8\u9001(pushed) +gb.createdNewTag = \u5efa\u7acb\u65b0\u6a19\u7c64 +gb.deletedTag = \u522a\u9664\u6a19\u7c64 +gb.pushedNewBranch = \u5df2\u63a8\u9001(pushed)\u4e4b\u5206\u652f - +gb.createdNewBranch = \u5efa\u7acb\u65b0\u5206\u652f +gb.deletedBranch = \u5df2\u522a\u9664\u7684\u5206\u652f +gb.createdNewPullRequest = \u5efa\u7acb pull request +gb.mergedPullRequest = \u5408\u4f75\u63a8\u9001\u8981\u6c42 +gb.rewind = REWIND +gb.star = \u91cd\u8981 +gb.unstar = \u53d6\u6d88 +gb.stargazers = stargazers +gb.starredRepositories = \u91cd\u8981\u7684\u7248\u672c\u5eab +gb.failedToUpdateUser = \u7121\u6cd5\u66f4\u65b0\u4f7f\u7528\u8005\u5e33\u865f +gb.myRepositories = \u6211\u7684\u7248\u672c\u5eab gb.noActivity = \u904e\u53bb{0}\u5929\u4f86,\u4e26\u6c92\u6709\u6d3b\u52d5\u7d00\u9304 +gb.findSomeRepositories = \u641c\u5c0b\u7248\u672c\u5eab +gb.metricAuthorExclusions = \u7d71\u8a08\u6642\u6392\u9664\u6d3b\u8e8d\u5e33\u6236 +gb.myDashboard = \u5100\u8868\u677f +gb.failedToFindAccount = \u7121\u6cd5\u641c\u5c0b\u5230\u5e33\u865f"{0}" +gb.reflog = \u76f8\u95dc\u65e5\u8a8c +gb.active = \u6d3b\u52d5 +gb.starred = \u91cd\u8981 +gb.owned = \u64c1\u6709 +gb.starredAndOwned = \u91cd\u8981 & \u64c1\u6709 +gb.reviewPatchset = {0}\u500breview {1}\u500bpatchset +gb.todaysActivityStats = \u4eca\u5929/\u6709{2}\u500b\u4f5c\u8005\u5b8c\u6210{1}\u500b\u63d0\u4ea4 +gb.todaysActivityNone = \u4eca\u5929/\u7121 gb.noActivityToday = \u4eca\u5929\u6c92\u6709\u6d3b\u52d5\u7d00\u9304 -gb.noComments = \u6c92\u6709\u5099\u8a3b +gb.anonymousUser = +gb.commitMessageRenderer = \u63d0\u4ea4\u8a0a\u606f\u5448\u73fe\u65b9\u5f0f +gb.diffStat = \u65b0\u589e{0}\u5217\u8207\u522a\u9664{1}\u5217 +gb.home = \u9996\u9801 +gb.isMirror = \u8a72\u7248\u672c\u5eab\u70ba\u93e1\u50cf(mirror) +gb.mirrorOf = {0}\u7684\u93e1\u50cf +gb.mirrorWarning = \u8a72\u7248\u672c\u5eab\u5c6c\u65bc\u93e1\u50cf, \u4e0d\u80fd\u5920\u63a5\u6536\u63a8\u9001(push) +gb.docsWelcome1 = \u4f60\u53ef\u4ee5\u4f7f\u7528\u6a94\u6848\u5340\u5efa\u7acb\u7248\u672c\u5eab\u7684\u6559\u5b78\u6a94\u6848 +gb.docsWelcome2 = \u63d0\u4ea4README.md \u6216 HOME.md\u5f8c,\u518d\u958b\u59cb\u65b0\u7684\u7248\u672c\u5eab +gb.createReadme = \u5efa\u7acbREADME\u6a94\u6848 +gb.responsible = \u8ca0\u8cac\u4eba\u54e1 +gb.createdThisTicket = \u5df2\u958b\u7acb\u7684\u4efb\u52d9 +gb.proposedThisChange = proposed this change +gb.uploadedPatchsetN = \u88dc\u4e01{0}\u5df2\u4e0a\u50b3 +gb.uploadedPatchsetNRevisionN = \u88dc\u4e01{0}\u4fee\u6539\u7248\u672c{1}\u5df2\u4e0a\u50b3 +gb.mergedPatchset = \u5c07\u88dc\u4e01\u5408\u4f75 +gb.commented = \u5df2\u8a3b\u89e3 gb.noDescriptionGiven = \u6c92\u6709\u7d66\u4e88\u7c21\u8ff0 -gb.noFederation = Sorry, {0} is not configured to federate with any Gitblit instances. -gb.noForks = {0}\u6c92\u6709\u5206\u652f(fork) -gb.noGitblitFound = Sorry, {0} could not find a Gitblit instance at {1}. -gb.noHits = \u7121\u9ede\u64ca -gb.noIndexedRepositoriesWarning = \u8ddf\u4f60\u76f8\u95dc\u7684\u6587\u4ef6\u5eab\u4e26\u6c92\u6709\u505aLucene\u7d22\u5f15 -gb.noMaximum = \u7121\u6700\u5927\u503c -gb.noMilestoneSelected = \u672a\u9078\u53d6\u91cc\u7a0b\u7891 -gb.none = \u7121 -gb.nOpenTickets = {0}\u9805\u958b\u555f\u4e2d -gb.noPermission = \u522a\u9664\u9019\u500b\u6b0a\u9650 -gb.noProposals = \u62b1\u6b49, {0}\u6b64\u6642\u4e26\u4e0d\u662f\u53ef\u63a5\u53d7\u7684\u8a08\u756b -gb.noSelectedRepositoriesWarning = \u8acb\u81f3\u5c11\u9078\u64c7\u4e00\u500b\u6587\u4ef6\u5eab -gb.notifyChangedOpenTickets = \u5df2\u958b\u555f\u7684\u4efb\u52d9\u55ae\u6709\u7570\u52d5\u8acb\u767c\u9001\u901a\u77e5 -gb.notRestricted = \u533f\u540d\u72c0\u614b\u53ef\u4ee5View, Clone\u8207Push -gb.notSpecified = \u7121\u6307\u5b9a +gb.toBranch = \u5230\u5206\u652f {0} +gb.createdBy = \u5efa\u7acb\u8005 +gb.oneParticipant = {0}\u53c3\u8207 gb.nParticipants = {0}\u500b\u53c3\u8207 -gb.nTotalTickets = \u7e3d\u5171{0}\u9805 -gb.object = \u7269\u4ef6 -gb.of = \u7684 -gb.ok = ok -gb.oneAttachment = {0}\u500b\u9644\u4ef6 +gb.noComments = \u6c92\u6709\u5099\u8a3b gb.oneComment = {0}\u500b\u8a3b\u89e3 -gb.oneCommit = 1\u500b\u63d0\u4ea4 -gb.oneCommitTo = 1\u500b\u63d0\u4ea4\u5230 -gb.oneMoreCommit = \u9084\u6709\u4e00\u500b\u63d0\u4ea4 \u00bb -gb.oneParticipant = {0}\u53c3\u8207 -gb.OneProposalToReview = \u6709\u4e00\u500b\u4e32\u9023\u7684\u63d0\u6848\u7b49\u5f85\u5be9\u67e5 -gb.opacityAdjust = Adjust opacity +gb.nComments = {0}\u500b\u8a3b\u89e3 +gb.oneAttachment = +gb.nAttachments = {0}\u500b\u9644\u4ef6 +gb.milestone = milestone +gb.compareToMergeBase = \u6bd4\u5c0d\u5f8c,\u5408\u4f75\u5230\u4e3b\u8981\u5de5\u4f5c\u5340 +gb.compareToN = \u8207{0}\u9032\u884c\u6bd4\u5c0d gb.open = \u958b\u555f -gb.openMilestones = \u6253\u958b\u91cc\u7a0b\u7891 -gb.organization = \u7d44\u7e54 -gb.organizationalUnit = \u7d44\u7e54\u55ae\u4f4d -gb.origin = origin -gb.originDescription = \u6b64\u6587\u4ef6\u5eabURL\u5df2\u7d93\u88ab\u8907\u88fd(cloned)\u4e86 -gb.overdue = \u904e\u671f -gb.overview = \u6982\u89c0 -gb.owned = \u64c1\u6709\u7684 -gb.owner = \u64c1\u6709\u8005 -gb.ownerDescription = \u64c1\u6709\u8005\u53ef\u4fee\u6539\u6587\u4ef6\u5eab\u8a2d\u5b9a\u503c -gb.ownerPermission = \u6587\u4ef6\u5eab\u6240\u6709\u8005 -gb.owners = \u6240\u6709\u8005 -gb.ownersDescription = \u6240\u6709\u8005\u53ef\u4ee5\u7ba1\u7406\u6587\u4ef6\u5eab,\u4f46\u662f\u4e0d\u5141\u8a31\u4fee\u6539\u540d\u7a31(\u79c1\u4eba\u6587\u4ef6\u5eab\u4f8b\u5916) -gb.pageFirst = \u7b2c\u4e00\u7b46 -gb.pageNext = \u4e0b\u4e00\u9801 -gb.pagePrevious = \u4e0a\u4e00\u9801 -gb.pages = \u6587\u4ef6 -gb.parent = \u4e0a\u500b\u7248\u672c -gb.password = \u5bc6\u78bc -gb.passwordChangeAborted = \u53d6\u6d88\u5bc6\u78bc\u8b8a\u66f4 -gb.passwordChanged = \u5bc6\u78bc\u8b8a\u66f4\u6210\u529f -gb.passwordHint = \u5bc6\u78bc\u63d0\u793a -gb.passwordHintRequired = \u5bc6\u78bc\u63d0\u793a(\u5fc5\u8981) -gb.passwordsDoNotMatch = \u5bc6\u78bc\u4e0d\u76f8\u7b26 -gb.passwordTooShort = \u5bc6\u78bc\u904e\u77ed, \u6700\u5c11{0}\u500b\u5b57\u5143 -gb.patch = \u4fee\u88dc\u6a94 -gb.patchset = \u88dc\u4e01 -gb.patchsetAlreadyMerged = \u8a72\u88dc\u4e01\u5df2\u7d93\u5408\u4f75\u5230{0} +gb.closed = \u95dc\u9589 +gb.merged = \u5df2\u5408\u4f75 +gb.ticketPatchset = {0}\u4efb\u52d9\u55ae,{1}\u88dc\u4e01 gb.patchsetMergeable = \u8a72\u88dc\u4e01\u53ef\u4ee5\u81ea\u52d5\u8207{0}\u5408\u4f75 gb.patchsetMergeableMore = \u4f7f\u7528\u547d\u4ee4\u529f\u80fd,\u8b93\u6b64\u88dc\u4e01\u53ef\u4ee5\u8207{0}\u5408\u4f75 -gb.patchsetN = \u88dc\u4e01{0} -gb.patchsetNotApproved = \u8a72\u88dc\u4e01\u7248\u672c\u4e26\u6c92\u6709\u88ab\u6279\u51c6\u8207{0}\u5408\u4f75 -gb.patchsetNotApprovedMore = \u8a72\u88dc\u4e01\u5fc5\u9808\u7531\u5be9\u67e5\u8005\u6279\u51c6 -gb.patchsetNotMergeable = \u8a72\u88dc\u4e01\u4e0d\u80fd\u81ea\u52d5\u8207{0}\u5408\u4f75 -gb.patchsetNotMergeableMore = \u5fc5\u9808\u4ee5rebased\u6216\u662f\u624b\u52d5\u8207{0}\u5408\u4f75\u7684\u65b9\u5f0f\u624d\u80fd\u89e3\u6c7a\u8a72\u88dc\u4e01\u9020\u6210\u7684\u885d\u7a81 -gb.patchsetVetoedMore = \u5be9\u8996\u8005\u5df2\u7d93\u5c0d\u6b64\u88dc\u4e01\u6295\u7968 -gb.permission = \u6b0a\u9650 -gb.permissions = \u6b0a\u9650 -gb.permittedTeams = permitted teams -gb.permittedUsers = permitted users -gb.personalRepositories = \u500b\u4eba\u6587\u4ef6\u5eab -gb.pleaseGenerateClientCertificate = \u8acb\u7522\u751f\u7d66{0}\u4f7f\u7528\u7684\u7528\u6236\u7aef\u8b49\u66f8 -gb.pleaseSelectGitIgnore = \u8acb\u9078\u64c7\u4e00\u500b.gitignore\u6a94\u6848 -gb.pleaseSelectProject = \u8acb\u9078\u64c7\u5c08\u6848! -gb.pleaseSetDestinationUrl = Please enter a destination url for your proposal\! -gb.pleaseSetGitblitUrl = \u8acb\u8f38\u5165Gitblit URL ! -gb.pleaseSetRepositoryName = \u8acb\u8a2d\u5b9a\u7248\u672c\u5eab\u540d\u7a31 -gb.pleaseSetTeamName = \u8acb\u8f38\u5165\u5718\u968a\u540d\u7a31 -gb.pleaseSetUsername = \u8acb\u8f38\u5165\u4f7f\u7528\u8005\u540d\u7a31 -gb.plugins = \u63d2\u4ef6 -gb.postReceiveDescription = \u63a5\u5230\u63d0\u4ea4\u7533\u8acb\u5f8c,\u4e26\u4e14\u5728refs\u5b8c\u7562\u5f8c, \u5c07\u6703\u57f7\u884cPost-receive hook..

This is the appropriate hook for notifications, build triggers, etc.

-gb.postReceiveScripts = post-receive\u8173\u672c -gb.preferences = \u9810\u8a2d\u5e38\u7528\u503c -gb.preparingFork = \u6b63\u5728\u6e96\u5099\u8907\u88fd\u4e2d(fork)... -gb.preReceiveDescription = \u63a5\u5230\u63d0\u4ea4\u7533\u8acb\u5f8c,\u4f46\u5728\u9084\u6c92\u6709\u66f4\u65b0refs\u524d, \u5c07\u6703\u57f7\u884cPre-receive hook.

This is the appropriate hook for rejecting a push.

-gb.preReceiveScripts = pre-receive \u8173\u672c -gb.preview = \u9810\u89bd -gb.priority = \u512a\u5148 -gb.privilegeWithdrawn = \u53d6\u6d88\u6b0a\u9650 -gb.project = \u7fa4\u7d44 -gb.projects = \u7fa4\u7d44 -gb.properties = \u5c6c\u6027 -gb.proposal = \u63d0\u6848 -gb.proposalError = \u62b1\u6b49, {0} \u4efd\u5831\u544a\u767c\u751f\u9810\u671f\u5916\u7684\u932f\u8aa4! -gb.proposalFailed = Sorry, {0} did not receive any proposal data\! -gb.proposalReceived = Proposal successfully received by {0}. -gb.proposals = \u8981\u6c42\u806f\u5408\u7684\u63d0\u6848 -gb.proposalTickets = \u63d0\u6848\u4fee\u6539 -gb.proposedThisChange = proposed this change -gb.proposeInstructions = To start, craft a patchset and upload it with Git. Gitblit will link your patchset to this ticket by the id. -gb.proposePatchset = \u63d0\u51fa\u88dc\u4e01 -gb.proposePatchsetNote = \u6b61\u8fce\u5c0d\u6b64\u4efb\u52d9\u55ae\u63d0\u4f9b\u88dc\u4e01 -gb.proposeWith = propose a patchset with {0} -gb.ptCheckout = Fetch & checkout the current patchset to a review branch -gb.ptDescription = the Gitblit patchset tool -gb.ptDescription1 = Barnum is a command-line companion for Git that simplifies the syntax for working with Gitblit Tickets and Patchsets. -gb.ptDescription2 = Barnum requires Python 3 and native Git. It runs on Windows, Linux, and Mac OS X. -gb.ptMerge = \u53d6\u5f97\u76ee\u524d\u88dc\u4e01,\u7136\u5f8c\u8207\u4f60\u672c\u6a5f\u7aef\u7684\u5206\u652f\u5408\u4f75 -gb.ptSimplifiedCollaboration = simplified collaboration syntax -gb.ptSimplifiedMerge = simplified merge syntax -gb.publicKey = \u516c\u958b\u91d1\u9470 -gb.pushedNCommitsTo = {0}\u500b\u63d0\u4ea4\u5df2\u63a8\u9001\u81f3 -gb.pushedNewBranch = \u65b0\u5206\u652f\u5df2\u63a8\u9001(pushed) -gb.pushedNewTag = \u65b0\u6a19\u7c64\u5df2\u63a8\u9001(pushed) -gb.pushedOneCommitTo = 1\u500b\u63d0\u4ea4\u5df2\u63a8\u9001\u81f3 -gb.pushPermission = {0}(\u63a8\u9001) -gb.pushRestricted = authenticated push -gb.queries = \u67e5\u8a62\u7d50\u679c -gb.query = \u67e5\u8a62 -gb.queryHelp = \u652f\u63f4\u6a19\u6e96\u67e5\u8a62\u8a9e\u6cd5.

\u8a73\u60c5\u8acb\u53c3\u8003 Lucene Query Parser Syntax -gb.queryResults = results {0} - {1} ({2} hits) -gb.questionTickets = \u63d0\u554f -gb.raw = \u539f\u59cb -gb.reason = \u539f\u56e0 -gb.receive = \u63a5\u6536 -gb.received = \u5df2\u63a5\u6536 -gb.receiveSettings = \u8a2d\u5b9a\u63a5\u6536\u65b9\u5f0f -gb.receiveSettingsDescription = \u63a7\u7ba1\u63a8\u9001\u5230\u6587\u4ef6\u5eab\u7684\u63a5\u6536\u65b9\u5f0f -gb.recent = \u6700\u8fd1 -gb.recentActivity = \u6700\u8fd1\u6d3b\u8e8d\u72c0\u6cc1 -gb.recentActivityNone = \u904e\u53bb{0}\u5929/\u7121 -gb.recentActivityStats = \u904e\u53bb{0}\u5929,\u4e00\u5171\u6709{2}\u4eba\u57f7\u884c{1}\u4efd\u63d0\u4ea4 -gb.reflog = \u76f8\u95dc\u65e5\u8a8c -gb.refresh = \u5237\u65b0 -gb.refs = \u5f15\u7528 -gb.regexPermission = \u5df2\u7d93\u4f7f\u7528\u6b63\u898f\u8868\u793a\u5f0f(regular expression)"{0}" \u8a2d\u5b9a\u6b0a\u9650\u5b8c\u7562 -gb.registration = \u8a3b\u518a -gb.registrations = federation registrations -gb.releaseDate = \u767c\u8868\u65e5 -gb.remote = \u9060\u7aef -gb.removeVote = \u79fb\u9664\u6295\u7968 -gb.rename = \u6539\u540d\u7a31 -gb.repositories = \u6587\u4ef6\u5eab -gb.repository = \u7248\u672c\u5eab -gb.repositoryDeleted = \u7248\u672c\u5eab"{0}"\u5df2\u522a\u9664 -gb.repositoryDeleteFailed = \u522a\u9664\u7248\u672c\u5eab"{0}"\u5931\u6557! -gb.repositoryDoesNotAcceptPatchsets = \u8a72\u7248\u672c\u5eab\u4e0d\u63a5\u53d7\u88dc\u4e01 -gb.repositoryForked = \u7248\u672c\u5eab{0}\u5df2\u7d93\u5efa\u7acb\u5206\u652f(fork) -gb.repositoryForkFailed= \u5efa\u7acb\u5206\u652f(fork)\u5931\u6557 -gb.repositoryIsFrozen = \u8a72\u7248\u672c\u5eab\u5df2\u51cd\u7d50 -gb.repositoryIsMirror = \u8a72\u7248\u672c\u5eab\u70ba\u552f\u8b80\u8907\u672c -gb.repositoryNotSpecified = \u672a\u6307\u5b9a\u7248\u672c\u5eab! -gb.repositoryNotSpecifiedFor = \u7248\u672c\u5eab\u4e26\u6c92\u6709\u6307\u5b9a\u7d66 {0}\! -gb.repositoryPermissions = \u7248\u672c\u5eab\u6b0a\u9650 -gb.repositoryUrl = \u7248\u672c\u5eab url -gb.requestTickets = \u512a\u5316 & \u4efb\u52d9 -gb.requireApproval = \u9700\u6279\u51c6 -gb.requireApprovalDescription = \u5408\u4f75\u6309\u9215\u555f\u7528\u524d,\u88dc\u4e01\u5305\u5fc5\u9808\u5148\u6279\u51c6 -gb.reset = \u6e05\u9664 -gb.responsible = \u8ca0\u8cac\u4eba\u54e1 -gb.restrictedRepositories = restricted repositories -gb.review = \u8907\u67e5(review) -gb.reviewedPatchsetRev = reviewed patchset {0} revision {1}\: {2} -gb.reviewers = \u5be9\u67e5\u8005 -gb.reviewPatchset = review {0} patchset {1} -gb.reviews = reviews -gb.revisionHistory = \u4fee\u6539\u7d00\u9304 -gb.revokeCertificate = \u64a4\u56de\u8b49\u66f8 -gb.revokeCertificateReason = \u8acb\u8f38\u5165\u64a4\u56de\u8b49\u66f8\u7406\u7531 -gb.revoked = \u5df2\u64a4\u92b7 -gb.rewind = REWIND -gb.rewindPermission = {0} (push, ref creation+deletion+rewind) -gb.save = \u5132\u5b58 -gb.search = \u641c\u5c0b -gb.searchForAuthor = Search for commits authored by -gb.searchForCommitter = Search for commits committed by -gb.searchTickets = \u641c\u5c0b\u4efb\u52d9\u55ae -gb.searchTicketsTooltip = \u627e\u5230{0}\u4efd\u4efb\u52d9\u55ae -gb.searchTooltip = \u641c\u5c0b{0} -gb.searchTypeTooltip = \u9078\u64c7\u641c\u5c0b\u985e\u578b -gb.selectAccessRestriction = Please select access restriction\! -gb.selected = \u9078\u5b9a -gb.selectFederationStrategy = Please select federation strategy\! -gb.sendEmail = \u767cemail -gb.sendProposal = \u63d0\u6848 -gb.serialNumber = \u5e8f\u865f -gb.serveCertificate = \u555f\u7528\u4f7f\u7528\u6b64\u8b49\u66f8\u7684https\u529f\u80fd -gb.serverDoesNotAcceptPatchsets = \u672c\u4f3a\u670d\u5668\u4e0d\u63a5\u53d7\u88dc\u4e01 -gb.servers = \u4f3a\u670d\u5668 -gb.servletContainer = servlet\u5bb9\u5668 -gb.sessionEnded = session\u5df2\u7d93\u53d6\u6d88 -gb.setDefault = \u8a2d\u70ba\u9810\u8a2d\u503c -gb.settings = \u8a2d\u5b9a -gb.severity = \u91cd\u8981 -gb.sha1FingerPrint = SHA-1 Fingerprint -gb.show_whitespace = \u986f\u793a\u7a7a\u767d -gb.showHideDetails = \u986f\u793a/\u96b1\u85cf \u8a73\u89e3\u5167\u5bb9 -gb.showReadme = \u986f\u793areadme\u6587\u4ef6 -gb.showReadmeDescription = \u5728\u532f\u7e3d\u9801\u9762\u4e2d\u986f\u793a"readme"(markdown\u683c\u5f0f) -gb.showRemoteBranches = \u986f\u793a\u9060\u7aef\u5206\u652f -gb.showRemoteBranchesDescription = \u986f\u793a\u9060\u7aef\u5206\u652f(branches) -gb.signatureAlgorithm = \u7c3d\u7ae0\u6f14\u7b97\u6cd5 -gb.since = \u5f9e -gb.siteName = \u7ad9\u53f0\u540d\u7a31 -gb.siteNameDescription = \u4f3a\u670d\u5668\u7c21\u7a31 -gb.size = \u5bb9\u91cf -gb.skipSizeCalculation = \u7565\u904e\u5bb9\u91cf\u8a08\u7b97 -gb.skipSizeCalculationDescription = \u4e0d\u8a08\u7b97\u6587\u4ef6\u5eab\u5bb9\u91cf(\u52a0\u5feb\u7db2\u9801\u8f09\u5165\u901f\u5ea6) -gb.skipSummaryMetrics = \u7565\u904e\u91cf\u5316\u532f\u7e3d -gb.skipSummaryMetricsDescription = \u4e0d\u8981\u8a08\u7b97\u91cf\u5316\u4e26\u4e14\u986f\u793a\u5728\u532f\u7e3d\u9801\u9762\u4e0a(\u52a0\u5feb\u901f\u5ea6) +gb.patchsetAlreadyMerged = \u8a72\u88dc\u4e01\u5df2\u7d93\u5408\u4f75\u5230{0} +gb.patchsetNotMergeable = \u8a72\u88dc\u4e01\u4e0d\u80fd\u81ea\u52d5\u8207{0}\u5408\u4f75 +gb.patchsetNotMergeableMore = \u5fc5\u9808\u4ee5rebased\u6216\u662f\u624b\u52d5\u8207{0}\u5408\u4f75\u7684\u65b9\u5f0f\u624d\u80fd\u89e3\u6c7a\u8a72\u88dc\u4e01\u9020\u6210\u7684\u885d\u7a81 +gb.patchsetNotApproved = \u8a72\u88dc\u4e01\u7248\u672c\u4e26\u6c92\u6709\u88ab\u6279\u51c6\u8207{0}\u5408\u4f75 +gb.patchsetNotApprovedMore = \u8a72\u88dc\u4e01\u5fc5\u9808\u7531\u5be9\u67e5\u8005\u6279\u51c6 +gb.patchsetVetoedMore = \u5be9\u67e5\u8005\u5df2\u7d93\u5c0d\u6b64\u88dc\u4e01\u6295\u7968 +gb.write = \u8f38\u5165 +gb.comment = \u8a3b\u89e3 +gb.preview = \u9810\u89bd +gb.leaveComment = \u7559\u4e0b\u8a3b\u89e3 +gb.showHideDetails = \u986f\u793a/\u96b1\u85cf \u8a73\u89e3\u5167\u5bb9 +gb.acceptNewPatchsets = \u5141\u8a31\u88dc\u4e01 +gb.acceptNewPatchsetsDescription = \u63a5\u53d7\u5230\u7248\u672c\u5eab\u9032\u884c\u4fee\u88dc\u52d5\u4f5c +gb.acceptNewTickets = \u5141\u8a31\u5efa\u7acb\u4efb\u52d9 +gb.acceptNewTicketsDescription = \u5141\u8a31\u65b0\u589e"\u81ed\u87f2","\u512a\u5316","\u4efb\u52d9"\u5404\u985e\u578b\u4efb\u52d9 +gb.requireApproval = \u9700\u6279\u51c6 +gb.requireApprovalDescription = \u5408\u4f75\u6309\u9215\u555f\u7528\u524d,\u88dc\u4e01\u5305\u5fc5\u9808\u5148\u6279\u51c6 +gb.topic = \u8a71\u984c +gb.proposalTickets = \u63d0\u6848\u4fee\u6539 +gb.bugTickets = \u81ed\u87f2 +gb.enhancementTickets = \u512a\u5316 +gb.taskTickets = \u4efb\u52d9 +gb.questionTickets = \u63d0\u554f +gb.requestTickets = \u512a\u5316 & \u4efb\u52d9 +gb.yourCreatedTickets = \u4f60\u65b0\u589e\u7684 +gb.yourWatchedTickets = \u4f60\u76e3\u770b\u7684 +gb.mentionsMeTickets = \u8207\u4f60\u76f8\u95dc +gb.updatedBy = \u66f4\u65b0\u8005 gb.sort = \u6392\u5e8f -gb.sortHighestPriority = \u6700\u9ad8\u512a\u5148 -gb.sortHighestSeverity = \u6700\u91cd\u8981 -gb.sortLeastComments = \u6700\u5c11\u5099\u8a3b -gb.sortLeastPatchsetRevisions = \u6700\u5c11\u88dc\u4e01\u4fee\u6539 +gb.sortNewest = \u6700\u65b0 +gb.sortOldest = \u6700\u820a +gb.sortMostRecentlyUpdated = \u6700\u8fd1\u66f4\u65b0 gb.sortLeastRecentlyUpdated = \u6700\u8fd1\u6700\u5c11\u8b8a\u52d5 -gb.sortLeastVotes = \u6700\u5c11\u6295\u7968 -gb.sortLowestPriority = \u6700\u4f4e\u512a\u5148 -gb.sortLowestSeverity = \u6700\u4e0d\u91cd\u8981 gb.sortMostComments = \u6700\u591a\u5099\u8a3b +gb.sortLeastComments = \u6700\u5c11\u5099\u8a3b gb.sortMostPatchsetRevisions = \u6700\u591a\u88dc\u4e01\u4fee\u6b63 -gb.sortMostRecentlyUpdated = \u6700\u8fd1\u66f4\u65b0 +gb.sortLeastPatchsetRevisions = \u6700\u5c11\u88dc\u4e01\u4fee\u6539 gb.sortMostVotes = \u6700\u591a\u6295\u7968 -gb.sortNewest = \u6700\u65b0 -gb.sortOldest = \u6700\u820a -gb.specified = \u6307\u5b9a\u7d66\u4e88(\u542b\u7cfb\u7d71\u9810\u8a2d) -gb.sshKeyCommentDescription = \u8acb\u8f38\u5165\u5099\u8a3b, \u82e5\u7121\u5099\u8a3b, \u5c07\u81ea\u8a02\u586b\u5165key data -gb.sshKeyPermissionDescription = \u6307\u5b9a\u8a72SSH key\u6240\u64c1\u6709\u7684\u5b58\u53d6\u6b0a\u9650 -gb.sshKeys = SSH Keys -gb.sshKeysDescription = SSH \u516c\u958b\u91d1\u9470\u662f\u5bc6\u78bc\u8a8d\u8b49\u5916\u66f4\u5b89\u5168\u7684\u9078\u9805 -gb.sslCertificateGenerated = \u6210\u529f\u7522\u751f\u7d66{0}\u7684\u670d\u5668SSL\u8b49\u66f8 -gb.sslCertificateGeneratedRestart = \u6210\u529f\u7522\u751f\u7d66{0}\u4f7f\u7528\u7684SSL\u8b49\u66f8\n\u4f60\u5fc5\u9808\u91cd\u65b0\u555f\u52d5Gitblit\u7248\u63a7\u4f3a\u670d\u5668\u624d\u80fd\u555f\u7528\u65b0\u7684\u8b49\u66f8\n\nf you are launching with the '--alias' parameter you will have to set that to ''--alias {0}''. -gb.star = \u91cd\u8981 -gb.stargazers = stargazers -gb.starred = \u91cd\u8981 -gb.starredAndOwned = \u91cd\u8981\u7684 & \u64c1\u6709\u7684 -gb.starredRepositories = \u91cd\u8981\u7684\u6587\u4ef6\u5eab -gb.starting = \u555f\u52d5\u4e2d -gb.stateProvince = \u5dde\u6216\u7701 -gb.stats = \u7d71\u8a08 -gb.status = \u72c0\u614b -gb.stepN = \u6b65\u9a5f{0} -gb.stopWatching = \u505c\u6b62\u8ffd\u8e64(watching) -gb.subject = \u6a19\u984c -gb.subscribe = \u8a02\u95b1 -gb.summary = \u532f\u7e3d -gb.superseded = \u5df2\u88ab\u66ff\u4ee3 -gb.tag = \u6a19\u7c64 -gb.tagger = tagger -gb.tags = \u6a19\u7c64 -gb.taskTickets = \u4efb\u52d9 -gb.team = \u5718\u968a -gb.teamCreated = \u5718\u968a"{0}"\u65b0\u589e\u6210\u529f. -gb.teamMembers = \u5718\u968a\u6210\u54e1 -gb.teamMemberships = \u5718\u968a\u6210\u54e1(memberships) -gb.teamMustSpecifyRepository = \u5718\u968a\u6700\u5c11\u8981\u6307\u5b9a\u4e00\u500b\u7248\u672c\u5eab -gb.teamName = \u5718\u968a\u540d\u7a31 -gb.teamNameUnavailable = \u5718\u968a"{0}"\u4e0d\u5b58\u5728. -gb.teamPermission = "{0}" \u5718\u968a\u6210\u54e1\u7684\u6b0a\u9650 -gb.teamPermissions = \u5718\u968a\u6b0a\u9650 -gb.teamPermissionsDescription = \u4f60\u53ef\u4ee5\u6307\u5b9a\u5718\u968a\u6b0a\u9650.\u9019\u4e9b\u8a2d\u5b9a\u5c07\u6703\u53d6\u4ee3\u539f\u672c\u5718\u968a\u9810\u8a2d\u6b0a\u9650 -gb.teams = \u53c3\u8207\u7684\u5718\u968a -gb.ticket = \u4efb\u52d9\u55ae -gb.ticketAssigned = \u5df2\u6307\u5b9a -gb.ticketComments = \u8a3b\u89e3 -gb.ticketId = \u4efb\u52d9\u55aeID -gb.ticketIsClosed = \u8a72\u4efb\u52d9\u55ae\u5df2\u7d93\u7d50\u6848 -gb.ticketN = \u4efb\u52d9\u55ae\u865f#{0} -gb.ticketOpenDate = \u767c\u884c\u65e5 -gb.ticketPatchset = {0}\u4efb\u52d9\u55ae,{1}\u88dc\u4e01 -gb.tickets = \u4efb\u52d9\u55ae -gb.ticketSettings = \u4efb\u52d9\u55ae\u5167\u5bb9\u8a2d\u5b9a -gb.ticketStatus = \u72c0\u614b -gb.ticketsWelcome = \u4f60\u53ef\u4ee5\u5229\u7528\u4efb\u52d9\u55ae\u7cfb\u7d71\u5efa\u69cb\u51fa\u5f85\u8fa6\u4e8b\u9805, \u81ed\u87f2\u56de\u5831\u5340\u4ee5\u53ca\u88dc\u4e01\u5305\u7684\u5354\u540c\u5408\u4f5c -gb.time.daysAgo = {0}\u5929\u524d -gb.time.hoursAgo = {0}\u5c0f\u6642\u524d -gb.time.inDays = {0}\u5929\u5167 -gb.time.inHours = {0}\u5c0f\u6642\u5167 -gb.time.inMinutes = {0}\u5206\u9418\u5167 -gb.time.justNow = \u525b\u525b -gb.time.minsAgo = {0}\u5206\u9418\u524d -gb.time.monthsAgo = {0}\u6708\u524d -gb.time.oneYearAgo = 1\u5e74\u524d -gb.time.today = \u4eca\u5929 -gb.time.weeksAgo = {0}\u5468\u524d -gb.time.yearsAgo = {0}\u5e74\u524d -gb.time.yesterday = \u6628\u5929 -gb.title = \u6a19\u984c -gb.to = to -gb.toBranch = to {0} -gb.todaysActivityNone = \u4eca\u5929/\u7121 -gb.todaysActivityStats = \u4eca\u5929/\u6709{2}\u500b\u4f5c\u8005\u5b8c\u6210{1}\u500b\u63d0\u4ea4 -gb.token = token -gb.tokenAllDescription = \u6240\u6709\u7248\u672c\u5eab,\u4f7f\u7528\u8005\u8207\u8a2d\u5b9a -gb.tokenJurDescription = \u6240\u6709\u7248\u672c\u5eab -gb.tokens = federation tokens -gb.tokenUnrDescription = \u6240\u6709\u7248\u672c\u5eab\u8207\u4f7f\u7528\u8005 -gb.topic = \u8a71\u984c +gb.sortLeastVotes = \u6700\u5c11\u6295\u7968 gb.topicsAndLabels = \u8a71\u984c\u8207\u6a19\u8a18 -gb.transportPreference = \u9810\u8a2d\u901a\u8a0a\u5354\u5b9a -gb.transportPreferenceDescription = \u8a2d\u5b9a\u4f60\u5e38\u7528\u7684\u9023\u7dda\u901a\u8a0a\u5354\u5b9a\u4ee5\u7528\u4f86\u8907\u88fd(clone) -gb.tree = \u76ee\u9304 -gb.type = \u985e\u578b -gb.unauthorizedAccessForRepository = \u7248\u672c\u5eab\u672a\u6388\u6b0a\u5b58\u53d6 -gb.undefinedQueryWarning = \u672a\u8a2d\u5b9a\u67e5\u8a62\u689d\u4ef6 -gb.unspecified = \u672a\u6307\u5b9a -gb.unstar = \u53d6\u6d88 +gb.milestones = milestones +gb.noMilestoneSelected = \u672a\u9078\u53d6milestone +gb.notSpecified = \u7121\u6307\u5b9a +gb.due = \u622a\u6b62 +gb.queries = \u67e5\u8a62\u7d50\u679c +gb.searchTicketsTooltip = \u627e\u5230{0}\u4efd\u4efb\u52d9 +gb.searchTickets = \u641c\u5c0b\u4efb\u52d9 +gb.new = \u5efa\u7acb +gb.newTicket = \u65b0\u589e\u4efb\u52d9 +gb.editTicket = \u4fee\u6539\u4efb\u52d9 +gb.ticketsWelcome = \u4f60\u53ef\u4ee5\u5229\u7528\u4efb\u52d9\u7cfb\u7d71\u5efa\u69cb\u51fa\u5f85\u8fa6\u4e8b\u9805, \u81ed\u87f2\u56de\u5831\u5340\u4ee5\u53ca\u88dc\u4e01\u5305\u7684\u5354\u540c\u5408\u4f5c +gb.createFirstTicket = \u6309\u6b64\u5efa\u7acb\u7b2c\u4e00\u500b\u4efb\u52d9 +gb.title = \u6a19\u984c +gb.changedStatus = changed the status +gb.discussion = \u8a0e\u8ad6 gb.updated = \u5df2\u66f4\u65b0 -gb.updatedBy = updated by -gb.uploadedPatchsetN = \u88dc\u4e01{0}\u5df2\u4e0a\u50b3 -gb.uploadedPatchsetNRevisionN = \u88dc\u4e01{0}\u4fee\u6539\u7248\u672c{1}\u5df2\u4e0a\u50b3 -gb.url = URL -gb.useDocsDescription = \u8a08\u7b97\u6587\u4ef6\u5eab\u88e1\u9762\u7684Markdown\u6a94\u6848 -gb.useIncrementalPushTagsDescription = \u63a8\u9001\u6642\u5c07\u81ea\u52d5\u65b0\u589e\u6a19\u7c64\u865f\u78bc -gb.userCreated = \u6210\u529f\u5efa\u7acb\u65b0\u4f7f\u7528\u8005"{0}" -gb.userDeleted = \u4f7f\u7528\u8005"{0}"\u5df2\u522a\u9664 -gb.userDeleteFailed = \u4f7f\u7528\u8005"{0}"\u522a\u9664\u5931\u6557 -gb.username = \u4f7f\u7528\u8005\u540d\u7a31 -gb.usernameUnavailable = \u4f7f\u7528\u8005\u540d\u7a31"{0}"\u4e0d\u53ef\u7528 -gb.userPermissions = \u4f7f\u7528\u8005\u6b0a\u9650 -gb.userPermissionsDescription = \u4f60\u53ef\u4ee5\u91dd\u5c0d\u5e33\u865f\u8a2d\u5b9a\u6b0a\u9650(\u9019\u4e9b\u8a2d\u5b9a\u5c07\u8986\u84cb\u5718\u968a\u6216\u5176\u4ed6\u6b0a\u9650) -gb.users = \u4f7f\u7528\u8005 -gb.userServiceDoesNotPermitAddUser = {0}\u4e0d\u5141\u8a31\u65b0\u589e\u4f7f\u7528\u8005\u5e33\u865f -gb.userServiceDoesNotPermitPasswordChanges = {0}\u4e0d\u5141\u8a31\u4fee\u6539\u5bc6\u78bc -gb.useTicketsDescription = readonly, distributed Ticgit issues -gb.validFrom = valid from -gb.validity = validity -gb.validUntil = valid until -gb.verifyCommitter = \u63d0\u4ea4\u8005\u9700\u9a57\u8b49 -gb.verifyCommitterDescription = \u9700\u8981\u63d0\u4ea4\u8005\u7b26\u5408\u63a8\u9001\u5e33\u865f -gb.verifyCommitterNote = \u6240\u6709\u5408\u4f75\u52d5\u4f5c\u7686\u9808\u5f37\u5236\u4f7f\u7528"--no-ff"\u53c3\u6578 -gb.version = \u7248\u672c -gb.veto = veto -gb.view = \u6aa2\u8996 -gb.viewAccess = \u4f60\u6c92\u6709Gitblit\u8b80\u53d6\u6216\u662f\u4fee\u6539\u6b0a\u9650 -gb.viewCertificate = \u6aa2\u8996\u8b49\u66f8 -gb.viewComparison = \u6bd4\u8f03\u9019{0}\u500b\u63d0\u4ea4 \u00bb -gb.viewPermission = {0} (\u6aa2\u8996) -gb.viewPolicy = Restrict View, Clone, & Push -gb.viewPolicyDescription = \u9078\u64c7\u53ef\u4ee5\u5728\u6587\u4ef6\u5eab\u6aa2\u8996,\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u7684\u4f7f\u7528\u8005, \u9664\u6b64\u4e4b\u5916\u5176\u4ed6\u4eba\u7686\u7121\u6b0a\u9650 -gb.viewRestricted = authenticated view, clone, & push +gb.proposePatchset = \u63d0\u51fa\u88dc\u4e01 +gb.proposePatchsetNote = \u6b61\u8fce\u5c0d\u6b64\u4efb\u52d9\u63d0\u4f9b\u88dc\u4e01 +gb.proposeInstructions = \u9996\u5148, \u5efa\u7acb\u88dc\u4e01\u4e26\u4e14\u540c\u6b65\u5230\u6b64gitblit\u4f3a\u670d\u5668. Gitblit \u8b93\u88dc\u4e01\u8207\u672c\u6b21\u4efb\u52d9ID(ticket ID)\u9023\u7d50. +gb.proposeWith = \u5982\u4f55\u5728{0} \u4e0a\u5efa\u7acb\u88dc\u4e01 +gb.revisionHistory = \u4fee\u6539\u7d00\u9304 +gb.merge = \u5408\u4f75 +gb.action = \u52d5\u4f5c +gb.patchset = \u88dc\u4e01 +gb.all = \u5168\u90e8 +gb.mergeBase = \u57fa\u672c\u5408\u4f75 +gb.checkout = \u6aa2\u51fa(checkout) +gb.checkoutViaCommandLine = \u4f7f\u7528\u6307\u4ee4Checkout +gb.checkoutViaCommandLineNote = \u4f60\u53ef\u4ee5\u5f9e\u4f60\u7248\u672c\u5eab\u4e2dcheckout\u4e00\u4efd,\u7136\u5f8c\u9032\u884c\u6e2c\u8a66 +gb.checkoutStep1 = Fetch the current patchset \u2014 run this from your project directory +gb.checkoutStep2 = \u5c07\u8a72\u88dc\u4e01\u8f49\u51fa\u5230\u65b0\u7684\u5206\u652f\u5f8c\u7528\u4f86\u6aa2\u8996 +gb.mergingViaCommandLine = \u7d93\u7531\u6307\u4ee4\u57f7\u884c\u5408\u4f75 +gb.mergingViaCommandLineNote = \u5982\u679c\u4f60\u4e0d\u60f3\u8981\u4f7f\u7528\u81ea\u52d5\u5408\u4f75\u529f\u80fd,\u6216\u662f\u6309\u4e0b\u5408\u4f75\u6309\u9215, \u4f60\u53ef\u4ee5\u4e0b\u6307\u4ee4\u624b\u52d5\u5408\u4f75 +gb.mergeStep1 = Check out a new branch to review the changes \u2014 run this from your project directory +gb.mergeStep2 = Bring in the proposed changes and review +gb.mergeStep3 = \u5c07\u63d0\u6848\u4fee\u6539\u5167\u5bb9\u66f4\u65b0\u5230\u4f3a\u670d\u5668\u4e0a +gb.download = \u4e0b\u8f09 +gb.ptDescription = Gitblit \u88dc\u4e01\u5de5\u5177 +gb.ptCheckout = Fetch & checkout the current patchset to a review branch +gb.ptMerge = \u53d6\u5f97\u76ee\u524dpatchset,\u7136\u5f8c\u8207\u4f60\u672c\u6a5f\u7aef\u7684\u5206\u652f\u5408\u4f75 +gb.ptDescription1 = Barnum is a command-line companion for Git that simplifies the syntax for working with Gitblit Tickets and Patchsets. +gb.ptSimplifiedCollaboration = simplified collaboration syntax +gb.ptSimplifiedMerge = simplified merge syntax +gb.ptDescription2 = Barnum requires Python 3 and native Git. It runs on Windows, Linux, and Mac OS X. +gb.stepN = \u6b65\u9a5f{0} +gb.watchers = \u76e3\u7763\u8005 +gb.votes = \u6295\u7968 gb.vote = \u5c0d{0}\u6295\u7968 -gb.voters = votes -gb.votes = votes -gb.warning = \u8b66\u544a gb.watch = \u76e3\u770b{0} -gb.watchers = \u76e3\u770b\u8005 +gb.removeVote = \u79fb\u9664\u6295\u7968 +gb.stopWatching = \u505c\u6b62\u8ffd\u8e64(watching) gb.watching = \u76e3\u770b\u4e2d -gb.workingCopy = \u5de5\u4f5c\u8907\u672c -gb.workingCopyWarning = \u8a72\u6587\u4ef6\u5eab\u4ecd\u6709\u5de5\u4f5c\u8907\u672c,\u56e0\u6b64\u7121\u6cd5\u63a5\u53d7\u63a8\u9001(push) -gb.write = write -gb.youDoNotHaveClonePermission = \u4f60\u4e0d\u5141\u8a31\u8907\u88fd(clone)\u6b64\u6587\u4ef6\u5eab +gb.comments = \u8a3b\u89e3 +gb.addComment = \u65b0\u589e\u8a3b\u89e3 +gb.export = \u532f\u51fa +gb.oneCommit = 1\u500b\u63d0\u4ea4 +gb.nCommits = {0}\u4efd\u63d0\u4ea4 +gb.addedOneCommit = \u63d0\u4ea41\u500b\u6a94\u6848 +gb.addedNCommits = {0}\u500b\u6a94\u6848\u63d0\u4ea4\u5b8c\u7562 +gb.commitsInPatchsetN = \u88dc\u4e01 {0} \u7684\u63d0\u4ea4 +gb.patchsetN = \u88dc\u4e01{0} +gb.reviewedPatchsetRev = reviewed patchset {0} revision {1}\: {2} +gb.review = \u6aa2\u67e5(review) +gb.reviews = \u6aa2\u67e5(reviews) +gb.veto = \u5426\u6c7a +gb.needsImprovement = \u9700\u8981\u512a\u5316 +gb.looksGood = \u770b\u8d77\u4f86\u5f88\u597d +gb.approve = \u901a\u904e +gb.hasNotReviewed = \u5c1a\u672a\u6aa2\u6838\u904e +gb.about = \u95dc\u65bc +gb.ticketN = \u4efb\u52d9\u7de8\u865f#{0} +gb.disableUser = \u505c\u7528\u5e33\u6236 +gb.disableUserDescription = \u8a72\u5e33\u6236\u7121\u6cd5\u4f7f\u7528 +gb.any = \u4efb\u4f55 +gb.milestoneProgress = {0}\u958b\u555f,{1}\u7d50\u675f +gb.nOpenTickets = {0}\u9805\u958b\u555f\u4e2d +gb.nClosedTickets = {0}\u9805\u7d50\u675f +gb.nTotalTickets = \u7e3d\u5171{0}\u9805 +gb.body = \u5167\u5bb9 +gb.mergeSha = mergeSha +gb.mergeTo = \u5408\u4f75\u5230 +gb.labels = \u6a19\u8a18 +gb.reviewers = \u5be9\u67e5\u8005 +gb.voters = votes +gb.mentions = \u63d0\u5230 +gb.canNotProposePatchset = \u4e0d\u80fd\u63d0\u4f9b\u88dc\u4e01 +gb.repositoryIsMirror = \u8a72\u7248\u672c\u5eab\u70ba\u552f\u8b80\u8907\u672c +gb.repositoryIsFrozen = \u8a72\u7248\u672c\u5eab\u5df2\u51cd\u7d50 +gb.repositoryDoesNotAcceptPatchsets = \u8a72\u7248\u672c\u5eab\u4e0d\u63a5\u53d7\u88dc\u4e01 +gb.serverDoesNotAcceptPatchsets = \u672c\u4f3a\u670d\u5668\u4e0d\u63a5\u53d7\u88dc\u4e01 +gb.ticketIsClosed = \u8a72\u4efb\u52d9\u5df2\u7d93\u7d50\u6848 +gb.mergeToDescription = \u9810\u8a2d\u5c07\u6587\u4ef6\u76f8\u95dc\u88dc\u4e01\u5305\u8207\u6307\u5b9a\u5206\u652f(branch)\u5408\u4f75 +gb.anonymousCanNotPropose = \u533f\u540d\u8005\u4e0d\u80fd\u63d0\u4f9b\u88dc\u4e01 +gb.youDoNotHaveClonePermission = \u4f60\u4e0d\u5141\u8a31\u8907\u88fd(clone)\u6b64\u7248\u672c\u5eab +gb.myTickets = \u6211\u7684\u4efb\u52d9 gb.yourAssignedTickets = \u6307\u6d3e\u7d66\u4f60\u7684 -gb.yourCreatedTickets = \u7531\u4f60\u65b0\u589e\u7684 -gb.yourWatchedTickets = \u4f60\u60f3\u770b\u7684 -gb.zip = zip\u58d3\u7e2e\u6a94 -gb.ticketState = -gb.repositoryForkFailed = -gb.anonymousUser = -gb.oneAttachment = +gb.newMilestone = \u5efa\u7acbmilestone +gb.editMilestone = \u4fee\u6539milestone +gb.deleteMilestone = \u522a\u9664milestone"{0}"? +gb.milestoneDeleteFailed = \u522a\u9664milestone"{0}"\u5931\u6557 +gb.notifyChangedOpenTickets = \u5df2\u958b\u555f\u7684\u4efb\u52d9\u6709\u7570\u52d5\u8acb\u767c\u9001\u901a\u77e5 +gb.overdue = \u904e\u671f +gb.openMilestones = \u6253\u958b milestones +gb.closedMilestones = \u5df2\u95dc\u9589\u7684milestones +gb.administration = \u7ba1\u7406\u6b0a\u9650 +gb.plugins = \u5957\u4ef6 +gb.extensions = \u64f4\u5145 +gb.pleaseSelectProject = \u8acb\u9078\u64c7\u5c08\u6848! +gb.accessPolicy = \u5b58\u53d6\u653f\u7b56 +gb.accessPolicyDescription = \u9078\u64c7\u7528\u4f86\u63a7\u5236\u7248\u672c\u5eab\u7684\u5b58\u53d6\u653f\u7b56\u4ee5\u53ca\u6b0a\u9650\u8a2d\u5b9a +gb.anonymousPolicy = \u533f\u540d\u72c0\u614b\u53ef\u4ee5\u6aa2\u8996(view),\u8907\u88fd(clone)\u8207\u63a8\u9001(push) +gb.anonymousPolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u6aa2\u8996(view),\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u6587\u4ef6\u5230\u7248\u672c\u5eab +gb.authenticatedPushPolicy = Restrict Push (Authenticated) +gb.authenticatedPushPolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u6aa2\u8996\u8207\u8907\u88fd(clone). \u4f46\u53ea\u6709\u6210\u54e1\u6709RW+\u8207\u63a8\u9001(push)\u529f\u80fd. +gb.namedPushPolicy = \u6307\u5b9a\u63a8\u9001(Push) (\u7528\u6236) +gb.namedPushPolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u6aa2\u8996\u8207\u8907\u88fd(clone)\u7248\u672c\u5eab. \u53ef\u53e6\u5916\u6307\u5b9a\u8ab0\u80fd\u5920\u6709\u63a8\u9001\u529f\u80fd(push) +gb.clonePolicy = Restrict Clone & Push +gb.clonePolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u770b\u7248\u672c\u5eab. \u53ef\u53e6\u5916\u6307\u5b9a\u8ab0\u6709\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u6b0a\u9650 gb.viewPolicy = +gb.viewPolicyDescription = \u9078\u64c7\u53ef\u4ee5\u5728\u7248\u672c\u5eab\u6aa2\u8996,\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u7684\u4f7f\u7528\u8005, \u9664\u6b64\u4e4b\u5916\u5176\u4ed6\u4eba\u7686\u7121\u6b0a\u9650 +gb.initialCommit = \u521d\u6b21\u63d0\u4ea4 +gb.initialCommitDescription = \u4ee5\u4e0b\u6b65\u9a5f\u5c07\u99ac\u4e0a\u57f7\u884cgit clone.\u5982\u679c\u4f60\u672c\u6a5f\u5df2\u6709\u6b64\u7248\u672c\u5eab\u4e14\u57f7\u884c\u904egit init,\u8acb\u8df3\u904e\u6b64\u6b65\u9a5f. +gb.initWithReadme = \u5305\u542bREADME\u6587\u4ef6 +gb.initWithReadmeDescription = \u7248\u672c\u5eab\u5c07\u7522\u751f\u7c21\u55aeREADME\u6587\u4ef6 +gb.initWithGitignore = \u5305\u542b .gitignore \u6a94\u6848 +gb.initWithGitignoreDescription = \u65b0\u589e\u4e00\u500b\u8a2d\u5b9a\u6a94\u7528\u4f86\u6307\u5b9a\u54ea\u4e9b\u6a94\u6848\u6216\u76ee\u9304\u9700\u8981\u5ffd\u7565 +gb.pleaseSelectGitIgnore = \u8acb\u9078\u64c7\u4e00\u500b.gitignore\u6a94\u6848 +gb.receive = \u63a5\u6536 +gb.permissions = \u6b0a\u9650 +gb.ownersDescription = \u6240\u6709\u8005\u53ef\u4ee5\u7ba1\u7406\u7248\u672c\u5eab,\u4f46\u662f\u4e0d\u5141\u8a31\u4fee\u6539\u540d\u7a31(\u500b\u4eba\u7248\u672c\u5eab\u4f8b\u5916) +gb.userPermissionsDescription = \u4f60\u53ef\u4ee5\u91dd\u5c0d\u5e33\u865f\u8a2d\u5b9a\u6b0a\u9650(\u9019\u4e9b\u8a2d\u5b9a\u5c07\u8986\u84cb\u5718\u968a\u6216\u5176\u4ed6\u6b0a\u9650) +gb.teamPermissionsDescription = \u4f60\u53ef\u4ee5\u6307\u5b9a\u5718\u968a\u6b0a\u9650.\u9019\u4e9b\u8a2d\u5b9a\u5c07\u6703\u53d6\u4ee3\u539f\u672c\u5718\u968a\u9810\u8a2d\u6b0a\u9650 +gb.ticketSettings = \u4efb\u52d9\u5167\u5bb9\u8a2d\u5b9a +gb.receiveSettings = \u8a2d\u5b9a\u63a5\u6536\u65b9\u5f0f +gb.receiveSettingsDescription = \u63a7\u7ba1\u63a8\u9001\u5230\u7248\u672c\u5eab\u7684\u63a5\u6536\u65b9\u5f0f +gb.preReceiveDescription = \u63a5\u5230\u63d0\u4ea4\u7533\u8acb\u5f8c,\u4f46\u5728\u9084\u6c92\u6709\u66f4\u65b0refs\u524d, \u5c07\u6703\u57f7\u884cPre-receive hook.

This is the appropriate hook for rejecting a push.

+gb.postReceiveDescription = \u63a5\u5230\u63d0\u4ea4\u7533\u8acb\u5f8c,\u4e26\u4e14\u5728refs\u5b8c\u7562\u5f8c, \u5c07\u6703\u57f7\u884cPost-receive hook..

This is the appropriate hook for notifications, build triggers, etc.

+gb.federationStrategyDescription = \u63a7\u5236\u5982\u4f55\u5c07\u7248\u672c\u5eab\u8207\u5176\u4ed6Gitblit\u7248\u63a7\u4f3a\u670d\u5668\u4e32\u9023 +gb.federationSetsDescription = \u6b64\u7248\u672c\u5eab\u5c07\u5305\u542b\u65bc\u6307\u5b9a\u7684federation sets +gb.miscellaneous = \u5176\u4ed6 +gb.originDescription = \u6b64\u7248\u672c\u5eabURL\u5df2\u7d93\u88ab\u8907\u88fd(cloned)\u4e86 +gb.gc = \u7cfb\u7d71\u8cc7\u6e90\u56de\u6536\u5668 +gb.garbageCollection = \u56de\u6536\u7cfb\u7d71\u8cc7\u6e90 +gb.garbageCollectionDescription = \u7cfb\u7d71\u8cc7\u6e90\u56de\u6536\u529f\u80fd\u5c07\u6703\u6574\u9813\u9b06\u6563\u7528\u6236\u7aef\u63a8\u9001(push)\u7684\u7269\u4ef6, \u4e5f\u6703\u79fb\u9664\u7248\u672c\u5eab\u4e0a\u7121\u7528\u7684\u7269\u4ef6 +gb.commitMessageRendererDescription = \u63d0\u4ea4\u8a0a\u606f\u53ef\u4ee5\u4f7f\u7528\u6587\u5b57\u6216\u662f\u6a19\u8a18\u8a9e\u8a00(markup)\u5448\u73fe +gb.preferences = \u9810\u8a2d\u5e38\u7528\u503c +gb.accountPreferences = \u5e33\u865f\u8a2d\u5b9a +gb.accountPreferencesDescription = \u8a2d\u5b9a\u5e33\u865f\u9810\u8a2d\u503c +gb.languagePreference = \u5e38\u7528\u8a9e\u8a00 +gb.languagePreferenceDescription = \u9078\u64c7\u8a9e\u7cfb +gb.emailMeOnMyTicketChanges = \u4efb\u52d9\u82e5\u6709\u8b8a\u66f4,\u8acb\u7acb\u5373(email)\u901a\u77e5\u6211 gb.emailMeOnMyTicketChangesDescription = +gb.displayNameDescription = \u5e0c\u671b\u986f\u793a\u7684\u540d\u7a31 +gb.emailAddressDescription = \u7528\u4f86\u63a5\u6536\u901a\u77e5\u7684\u4e3b\u8981\u96fb\u5b50\u90f5\u4ef6 +gb.sshKeys = SSH Keys +gb.sshKeysDescription = SSH \u516c\u958b\u91d1\u9470\u662f\u5bc6\u78bc\u8a8d\u8b49\u5916\u66f4\u5b89\u5168\u7684\u9078\u9805 +gb.addSshKey = \u65b0\u589e SSH Key +gb.key = \u91d1\u9470 +gb.sshKeyCommentDescription = \u8acb\u8f38\u5165\u5099\u8a3b, \u82e5\u7121\u5099\u8a3b, \u5c07\u81ea\u8a02\u586b\u5165key data +gb.sshKeyPermissionDescription = \u6307\u5b9a\u8a72SSH key\u6240\u64c1\u6709\u7684\u5b58\u53d6\u6b0a\u9650 +gb.transportPreference = \u9810\u8a2d\u901a\u8a0a\u5354\u5b9a +gb.transportPreferenceDescription = \u8a2d\u5b9a\u4f60\u5e38\u7528\u7684\u9023\u7dda\u7528\u4f86\u8907\u88fd(clone) +gb.anonymousUser= \u533f\u540d +gb.blinkComparator = Blink comparator +gb.deleteRepositoryDescription = \u7248\u672c\u5eab\u522a\u9664\u5c07\u7121\u6cd5\u9084\u539f +gb.deleteRepositoryHeader = \u522a\u9664\u7248\u672c\u5eab +gb.diffCopiedFile = \u6a94\u6848\u7531 {0} \u8907\u88fd +gb.diffDeletedFile = \u6a94\u6848\u5df2\u522a\u9664 +gb.diffDeletedFileSkipped = (\u522a\u9664) +gb.diffFileDiffTooLarge = \u6a94\u6848\u592a\u5927 +gb.diffNewFile = \u6bd4\u5c0d\u65b0\u6a94\u6848 +gb.diffRenamedFile = \u6a94\u540d\u7531 {0} \u4fee\u6539 +gb.diffTruncated = Diff truncated after the above file +gb.emailMeOnMyTicketChangesDescription = \u6211\u8655\u7406\u904e\u7684\u4efb\u52d9\u8acbemail\u901a\u77e5\u6211 +gb.ignore_whitespace =\u5ffd\u7565\u7a7a\u767d +gb.imgdiffSubtract = Subtract (black = identical) +gb.maintenanceTickets = \u7dad\u8b77 +gb.missingIntegrationBranchMore = \u76ee\u6a19\u5206\u652f\u4e0d\u5728\u6b64\u7248\u672c\u5eab +gb.oneAttachment = {0}\u500b\u9644\u4ef6 +gb.opacityAdjust = Adjust opacity +gb.priority = \u512a\u5148 +gb.repositoryForkFailed= \u5efa\u7acb\u5206\u652f(fork)\u5931\u6557 +gb.severity = \u91cd\u8981 +gb.show_whitespace = \u986f\u793a\u7a7a\u767d +gb.sortHighestPriority = \u6700\u9ad8 +gb.sortHighestSeverity = \u6700\u91cd\u8981 +gb.sortLowestPriority = \u6700\u4f4e +gb.sortLowestSeverity = \u6700\u4e0d\u91cd\u8981 +gb.ticketStatus = \u72c0\u614b +gb.viewPolicy = Restrict View, Clone, & Push +gb.allRepositories = \u6240\u6709\u7248\u672c\u5eab +gb.oid = \u7de8\u865f +gb.filestore = \u5927\u6a94\u6848\u5340 +gb.filestoreStats = \u5927\u6a94\u6848\u5340(Filestore)\u5305\u542b {0} \u6a94\u6848\u5bb9\u91cf {1}. (\u9084\u5269\u4e0b{2}\u53ef\u7528) +gb.statusChangedOn = \u4fee\u6539\u65e5\u671f +gb.statusChangedBy = \u4fee\u6539\u8005 +gb.filestoreHelp = \u6309\u6b64\u4e86\u89e3\u5927\u6a94\u6848\u5340(FileStore)\u5132\u5b58\u529f\u80fd +gb.editFile = \u7de8\u8f2f\u6a94\u6848 +gb.continueEditing = \u7e7c\u7e8c\u7de8\u8f2f +gb.commitChanges = Commit Changes +gb.fileNotMergeable = \u7121\u6cd5\u63d0\u4ea4 {0}. \u6a94\u6848\u7121\u6cd5\u81ea\u52d5\u5408\u4f75. +gb.fileCommitted = \u6210\u529f\u63d0\u4ea4 +gb.deletePatchset = \u522a\u9664 Patchset {0} +gb.deletePatchsetSuccess = \u5df2\u522a\u9664 Patchset {0}. +gb.deletePatchsetFailure = \u522a\u9664 Patchset {0} \u932f\u8aa4. +gb.referencedByCommit = Referenced by commit. +gb.referencedByTicket = Referenced by ticket. -- cgit v1.2.3 From 9f241db37f46abc1f6a052176eb072fa08230c19 Mon Sep 17 00:00:00 2001 From: william Date: Thu, 4 Aug 2016 15:47:48 +0800 Subject: 1.8.x tranditional chinese translation --- .../gitblit/wicket/GitBlitWebApp_zh_TW.properties | 48 ++++++++++------------ 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties index b2711cea..bf2d2c32 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties @@ -21,7 +21,6 @@ gb.object = \u7269\u4ef6 gb.ticketId = \u4efb\u52d9ID gb.ticketAssigned = \u5df2\u6307\u5b9a gb.ticketOpenDate = \u767c\u884c\u65e5 -gb.ticketState = gb.ticketComments = \u8a3b\u89e3 gb.view = \u6aa2\u8996 gb.local = \u672c\u5730\u7aef @@ -43,7 +42,7 @@ gb.pageFirst = \u7b2c\u4e00\u7b46 gb.pagePrevious = \u4e0a\u4e00\u9801 gb.pageNext = \u4e0b\u4e00\u9801 gb.head = HEAD -gb.blame = \u8ffd\u67e5 +gb.blame = \u8a73\u67e5 gb.login = \u767b\u5165 gb.logout = \u767b\u51fa gb.username = \u4f7f\u7528\u8005\u540d\u7a31 @@ -72,7 +71,7 @@ gb.edit = \u7de8\u8f2f gb.searchTypeTooltip = \u9078\u64c7\u641c\u5c0b\u985e\u578b gb.searchTooltip = \u641c\u5c0b{0} gb.delete = \u522a\u9664 -gb.docs = \u6a94\u6848\u5340 +gb.docs = \u6587\u4ef6 gb.accessRestriction = \u9650\u5236\u5b58\u53d6 gb.name = \u540d\u5b57 gb.enableTickets = \u555f\u7528\u4efb\u52d9(Ticket)\u7cfb\u7d71 @@ -84,9 +83,9 @@ gb.confirmPassword = \u78ba\u8a8d\u5bc6\u78bc gb.restrictedRepositories = \u53d7\u9650\u5236\u7684\u7248\u672c\u5eab gb.canAdmin = \u53ef\u7ba1\u7406 gb.notRestricted = \u533f\u540d\u72c0\u614b\u53ef\u4ee5View, Clone\u8207Push -gb.pushRestricted = authenticated push -gb.cloneRestricted = authenticated clone & push -gb.viewRestricted = authenticated view, clone, & push +gb.pushRestricted = \u6709\u6388\u6b0a\u624d\u80fd\u63a8\u9001(push) +gb.cloneRestricted = \u6709\u6388\u6b0a\u624d\u80fd\u8907\u88fd(clone)\u8207\u63a8\u9001(push) +gb.viewRestricted = \u6709\u6388\u6b0a\u624d\u80fd\u6aa2\u8996(view),\u8907\u88fd(clone), \u8207\u63a8\u9001(push) gb.useTicketsDescription = readonly, distributed Ticgit issues gb.useDocsDescription = \u8a08\u7b97\u7248\u672c\u5eab\u88e1\u9762\u7684Markdown\u6a94\u6848 gb.showRemoteBranchesDescription = \u986f\u793a\u9060\u7aef\u5206\u652f(branches) @@ -326,7 +325,7 @@ gb.fork = \u5efa\u7acb\u5206\u652f(fork) gb.forks = \u5206\u652f(forks) gb.forkRepository = \u7248\u672c\u5eab{0}\u5efa\u7acb\u5206\u652f(fork)? gb.repositoryForked = \u7248\u672c\u5eab{0}\u5df2\u7d93\u5efa\u7acb\u5206\u652f(fork) -gb.repositoryForkFailed = +gb.repositoryForkFailed = \u5efa\u7acb\u5206\u652f(fork)\u5931\u6557 gb.personalRepositories = \u500b\u4eba\u7248\u672c\u5eab gb.allowForks = \u5141\u8a31\u5efa\u7acb\u5206\u652f(forks) gb.allowForksDescription = \u5141\u8a31\u5df2\u6388\u6b0a\u7684\u4f7f\u7528\u8005\u5f9e\u7248\u672c\u5eab\u5efa\u7acb\u5206\u652f(fork) @@ -355,7 +354,7 @@ gb.noPermission = \u522a\u9664\u9019\u500b\u6b0a\u9650 gb.excludePermission = {0} \u6392\u9664(exclude) gb.viewPermission = {0} \u6aa2\u8996(view) gb.clonePermission = {0} \u8907\u88fd(clone) -gb.pushPermission = {0}(\u63a8\u9001) +gb.pushPermission = {0} \u63a8\u9001(push) gb.createPermission = {0} (push, ref creation) gb.deletePermission = {0} (push, ref creation+deletion) gb.rewindPermission = {0} (push, ref creation+deletion+rewind) @@ -460,16 +459,16 @@ gb.monthlyActivity = \u6708\u6d3b\u52d5 gb.myProfile = \u6211\u7684\u57fa\u672c\u8cc7\u6599 gb.compare = \u6bd4\u5c0d gb.manual = \u81ea\u884c\u8f38\u5165 -gb.from = from -gb.to = to +gb.from = \u5f9e +gb.to = \u81f3 gb.at = at -gb.of = \u7684 +gb.of = \u5c08\u6848\u70ba gb.in = in gb.moreChanges = \u6240\u6709\u8b8a\u66f4... gb.pushedNCommitsTo = {0}\u500b\u63d0\u4ea4\u5df2\u63a8\u9001\u81f3 gb.pushedOneCommitTo = 1\u500b\u63d0\u4ea4\u5df2\u63a8\u9001\u81f3 -gb.commitsTo = {0} \u63d0\u4ea4\u5230\u5206\u652f -gb.oneCommitTo = 1\u500b\u63d0\u4ea4\u5230\u5206\u652f +gb.commitsTo = {0} \u4efd\u63d0\u4ea4\u81f3\u5206\u652f +gb.oneCommitTo = 1\u500b\u63d0\u4ea4\u81f3\u5206\u652f gb.byNAuthors = \u7d93\u7531{0}\u500b\u4f5c\u8005 gb.byOneAuthor = \u7d93\u7531{0} gb.viewComparison = \u6bd4\u8f03\u9019{0}\u500b\u63d0\u4ea4 \u00bb @@ -504,7 +503,7 @@ gb.reviewPatchset = {0}\u500breview {1}\u500bpatchset gb.todaysActivityStats = \u4eca\u5929/\u6709{2}\u500b\u4f5c\u8005\u5b8c\u6210{1}\u500b\u63d0\u4ea4 gb.todaysActivityNone = \u4eca\u5929/\u7121 gb.noActivityToday = \u4eca\u5929\u6c92\u6709\u6d3b\u52d5\u7d00\u9304 -gb.anonymousUser = +gb.anonymousUser = \u533f\u540d gb.commitMessageRenderer = \u63d0\u4ea4\u8a0a\u606f\u5448\u73fe\u65b9\u5f0f gb.diffStat = \u65b0\u589e{0}\u5217\u8207\u522a\u9664{1}\u5217 gb.home = \u9996\u9801 @@ -529,7 +528,7 @@ gb.nParticipants = {0}\u500b\u53c3\u8207 gb.noComments = \u6c92\u6709\u5099\u8a3b gb.oneComment = {0}\u500b\u8a3b\u89e3 gb.nComments = {0}\u500b\u8a3b\u89e3 -gb.oneAttachment = +gb.oneAttachment = {0}\u500b\u9644\u4ef6 gb.nAttachments = {0}\u500b\u9644\u4ef6 gb.milestone = milestone gb.compareToMergeBase = \u6bd4\u5c0d\u5f8c,\u5408\u4f75\u5230\u4e3b\u8981\u5de5\u4f5c\u5340 @@ -682,8 +681,8 @@ gb.deleteMilestone = \u522a\u9664milestone"{0}"? gb.milestoneDeleteFailed = \u522a\u9664milestone"{0}"\u5931\u6557 gb.notifyChangedOpenTickets = \u5df2\u958b\u555f\u7684\u4efb\u52d9\u6709\u7570\u52d5\u8acb\u767c\u9001\u901a\u77e5 gb.overdue = \u904e\u671f -gb.openMilestones = \u6253\u958b milestones -gb.closedMilestones = \u5df2\u95dc\u9589\u7684milestones +gb.openMilestones = \u5df2\u958b\u555f\u7684 milestones +gb.closedMilestones = \u5df2\u95dc\u9589\u7684 milestones gb.administration = \u7ba1\u7406\u6b0a\u9650 gb.plugins = \u5957\u4ef6 gb.extensions = \u64f4\u5145 @@ -692,13 +691,13 @@ gb.accessPolicy = \u5b58\u53d6\u653f\u7b56 gb.accessPolicyDescription = \u9078\u64c7\u7528\u4f86\u63a7\u5236\u7248\u672c\u5eab\u7684\u5b58\u53d6\u653f\u7b56\u4ee5\u53ca\u6b0a\u9650\u8a2d\u5b9a gb.anonymousPolicy = \u533f\u540d\u72c0\u614b\u53ef\u4ee5\u6aa2\u8996(view),\u8907\u88fd(clone)\u8207\u63a8\u9001(push) gb.anonymousPolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u6aa2\u8996(view),\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u6587\u4ef6\u5230\u7248\u672c\u5eab -gb.authenticatedPushPolicy = Restrict Push (Authenticated) +gb.authenticatedPushPolicy = \u9650\u5236\u63a8\u9001(Push)(\u6388\u6b0a) gb.authenticatedPushPolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u6aa2\u8996\u8207\u8907\u88fd(clone). \u4f46\u53ea\u6709\u6210\u54e1\u6709RW+\u8207\u63a8\u9001(push)\u529f\u80fd. -gb.namedPushPolicy = \u6307\u5b9a\u63a8\u9001(Push) (\u7528\u6236) +gb.namedPushPolicy = \u9650\u5236\u63a8\u9001(Push)(\u6307\u5b9a\u5e33\u865f) gb.namedPushPolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u6aa2\u8996\u8207\u8907\u88fd(clone)\u7248\u672c\u5eab. \u53ef\u53e6\u5916\u6307\u5b9a\u8ab0\u80fd\u5920\u6709\u63a8\u9001\u529f\u80fd(push) -gb.clonePolicy = Restrict Clone & Push +gb.clonePolicy = \u9650\u5236\u8907\u88fd(Clone)\u8207\u63a8\u9001(Push) gb.clonePolicyDescription = \u6240\u6709\u4eba\u7686\u53ef\u770b\u7248\u672c\u5eab. \u53ef\u53e6\u5916\u6307\u5b9a\u8ab0\u6709\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u6b0a\u9650 -gb.viewPolicy = +gb.viewPolicy = \u9650\u5236\u6aa2\u8996(view),\u8907\u88fd(clone)\u8207\u63a8\u9001(push) gb.viewPolicyDescription = \u9078\u64c7\u53ef\u4ee5\u5728\u7248\u672c\u5eab\u6aa2\u8996,\u8907\u88fd(clone)\u8207\u63a8\u9001(push)\u7684\u4f7f\u7528\u8005, \u9664\u6b64\u4e4b\u5916\u5176\u4ed6\u4eba\u7686\u7121\u6b0a\u9650 gb.initialCommit = \u521d\u6b21\u63d0\u4ea4 gb.initialCommitDescription = \u4ee5\u4e0b\u6b65\u9a5f\u5c07\u99ac\u4e0a\u57f7\u884cgit clone.\u5982\u679c\u4f60\u672c\u6a5f\u5df2\u6709\u6b64\u7248\u672c\u5eab\u4e14\u57f7\u884c\u904egit init,\u8acb\u8df3\u904e\u6b64\u6b65\u9a5f. @@ -731,7 +730,7 @@ gb.accountPreferencesDescription = \u8a2d\u5b9a\u5e33\u865f\u9810\u8a2d\u503c gb.languagePreference = \u5e38\u7528\u8a9e\u8a00 gb.languagePreferenceDescription = \u9078\u64c7\u8a9e\u7cfb gb.emailMeOnMyTicketChanges = \u4efb\u52d9\u82e5\u6709\u8b8a\u66f4,\u8acb\u7acb\u5373(email)\u901a\u77e5\u6211 -gb.emailMeOnMyTicketChangesDescription = +gb.emailMeOnMyTicketChangesDescription =\u6211\u8655\u7406\u904e\u7684\u4efb\u52d9\u8acbemail\u901a\u77e5\u6211 gb.displayNameDescription = \u5e0c\u671b\u986f\u793a\u7684\u540d\u7a31 gb.emailAddressDescription = \u7528\u4f86\u63a5\u6536\u901a\u77e5\u7684\u4e3b\u8981\u96fb\u5b50\u90f5\u4ef6 gb.sshKeys = SSH Keys @@ -742,7 +741,6 @@ gb.sshKeyCommentDescription = \u8acb\u8f38\u5165\u5099\u8a3b, \u82e5\u7121\u5099 gb.sshKeyPermissionDescription = \u6307\u5b9a\u8a72SSH key\u6240\u64c1\u6709\u7684\u5b58\u53d6\u6b0a\u9650 gb.transportPreference = \u9810\u8a2d\u901a\u8a0a\u5354\u5b9a gb.transportPreferenceDescription = \u8a2d\u5b9a\u4f60\u5e38\u7528\u7684\u9023\u7dda\u7528\u4f86\u8907\u88fd(clone) -gb.anonymousUser= \u533f\u540d gb.blinkComparator = Blink comparator gb.deleteRepositoryDescription = \u7248\u672c\u5eab\u522a\u9664\u5c07\u7121\u6cd5\u9084\u539f gb.deleteRepositoryHeader = \u522a\u9664\u7248\u672c\u5eab @@ -753,15 +751,12 @@ gb.diffFileDiffTooLarge = \u6a94\u6848\u592a\u5927 gb.diffNewFile = \u6bd4\u5c0d\u65b0\u6a94\u6848 gb.diffRenamedFile = \u6a94\u540d\u7531 {0} \u4fee\u6539 gb.diffTruncated = Diff truncated after the above file -gb.emailMeOnMyTicketChangesDescription = \u6211\u8655\u7406\u904e\u7684\u4efb\u52d9\u8acbemail\u901a\u77e5\u6211 gb.ignore_whitespace =\u5ffd\u7565\u7a7a\u767d gb.imgdiffSubtract = Subtract (black = identical) gb.maintenanceTickets = \u7dad\u8b77 gb.missingIntegrationBranchMore = \u76ee\u6a19\u5206\u652f\u4e0d\u5728\u6b64\u7248\u672c\u5eab -gb.oneAttachment = {0}\u500b\u9644\u4ef6 gb.opacityAdjust = Adjust opacity gb.priority = \u512a\u5148 -gb.repositoryForkFailed= \u5efa\u7acb\u5206\u652f(fork)\u5931\u6557 gb.severity = \u91cd\u8981 gb.show_whitespace = \u986f\u793a\u7a7a\u767d gb.sortHighestPriority = \u6700\u9ad8 @@ -769,7 +764,6 @@ gb.sortHighestSeverity = \u6700\u91cd\u8981 gb.sortLowestPriority = \u6700\u4f4e gb.sortLowestSeverity = \u6700\u4e0d\u91cd\u8981 gb.ticketStatus = \u72c0\u614b -gb.viewPolicy = Restrict View, Clone, & Push gb.allRepositories = \u6240\u6709\u7248\u672c\u5eab gb.oid = \u7de8\u865f gb.filestore = \u5927\u6a94\u6848\u5340 -- cgit v1.2.3 From 2b9ad25b1a1f17cf06f31b08040a7ae098935b9d Mon Sep 17 00:00:00 2001 From: larsmaes Date: Fri, 16 Sep 2016 15:25:08 +0200 Subject: Spelling mistake fix pushedNewBranch was wrongly spelled --- src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties index f43b8f52..f71d67d7 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties @@ -476,7 +476,7 @@ gb.oneMoreCommit = 1 commit \u00bb gb.pushedNewTag = push nieuwe tag gb.createdNewTag = nieuwe tag gemaakt gb.deletedTag = tag verwijderd -gb.pushedNewBranch = push neuwe branch +gb.pushedNewBranch = push nieuwe branch gb.createdNewBranch = nieuwe branch gemaakt gb.deletedBranch = branch verwijderd gb.createdNewPullRequest = pull verzoek gemaakt -- cgit v1.2.3 From de3f435db5256bd5a106462dcfc0a2ccdce95450 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 26 Oct 2016 21:37:19 +0200 Subject: Issue #1076: load commit cache in a background thread * Make the CommitCache fully thread-safe. It was using a ConcurrentHashMap containing lists, but then handed out these lists. It also did multiple operations on that map that as a whole should be atomic. * Use isEmpty() instead of size() == 0. * Run the loading of the commit cache in a background daemon thread --- .../com/gitblit/manager/RepositoryManager.java | 62 ++++++----- src/main/java/com/gitblit/utils/ArrayUtils.java | 2 +- src/main/java/com/gitblit/utils/CommitCache.java | 117 ++++++++++++--------- 3 files changed, 103 insertions(+), 78 deletions(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/manager/RepositoryManager.java b/src/main/java/com/gitblit/manager/RepositoryManager.java index e9bf5b84..ed26c775 100644 --- a/src/main/java/com/gitblit/manager/RepositoryManager.java +++ b/src/main/java/com/gitblit/manager/RepositoryManager.java @@ -1952,39 +1952,47 @@ public class RepositoryManager implements IRepositoryManager { } protected void configureCommitCache() { - int daysToCache = settings.getInteger(Keys.web.activityCacheDays, 14); + final int daysToCache = settings.getInteger(Keys.web.activityCacheDays, 14); if (daysToCache <= 0) { logger.info("Commit cache is disabled"); - } else { - long start = System.nanoTime(); - long repoCount = 0; - long commitCount = 0; - logger.info(MessageFormat.format("Preparing {0} day commit cache. please wait...", daysToCache)); - CommitCache.instance().setCacheDays(daysToCache); - Date cutoff = CommitCache.instance().getCutoffDate(); - for (String repositoryName : getRepositoryList()) { - RepositoryModel model = getRepositoryModel(repositoryName); - if (model != null && model.hasCommits && model.lastChange.after(cutoff)) { - repoCount++; - Repository repository = getRepository(repositoryName); - for (RefModel ref : JGitUtils.getLocalBranches(repository, true, -1)) { - if (!ref.getDate().after(cutoff)) { - // branch not recently updated - continue; - } - List commits = CommitCache.instance().getCommits(repositoryName, repository, ref.getName()); - if (commits.size() > 0) { - logger.info(MessageFormat.format(" cached {0} commits for {1}:{2}", - commits.size(), repositoryName, ref.getName())); - commitCount += commits.size(); + return; + } + logger.info(MessageFormat.format("Preparing {0} day commit cache...", daysToCache)); + CommitCache.instance().setCacheDays(daysToCache); + Thread loader = new Thread() { + @Override + public void run() { + long start = System.nanoTime(); + long repoCount = 0; + long commitCount = 0; + Date cutoff = CommitCache.instance().getCutoffDate(); + for (String repositoryName : getRepositoryList()) { + RepositoryModel model = getRepositoryModel(repositoryName); + if (model != null && model.hasCommits && model.lastChange.after(cutoff)) { + repoCount++; + Repository repository = getRepository(repositoryName); + for (RefModel ref : JGitUtils.getLocalBranches(repository, true, -1)) { + if (!ref.getDate().after(cutoff)) { + // branch not recently updated + continue; + } + List commits = CommitCache.instance().getCommits(repositoryName, repository, ref.getName()); + if (commits.size() > 0) { + logger.info(MessageFormat.format(" cached {0} commits for {1}:{2}", + commits.size(), repositoryName, ref.getName())); + commitCount += commits.size(); + } } + repository.close(); } - repository.close(); } + logger.info(MessageFormat.format("built {0} day commit cache of {1} commits across {2} repositories in {3} msecs", + daysToCache, commitCount, repoCount, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start))); } - logger.info(MessageFormat.format("built {0} day commit cache of {1} commits across {2} repositories in {3} msecs", - daysToCache, commitCount, repoCount, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start))); - } + }; + loader.setName("CommitCacheLoader"); + loader.setDaemon(true); + loader.start(); } protected void confirmWriteAccess() { diff --git a/src/main/java/com/gitblit/utils/ArrayUtils.java b/src/main/java/com/gitblit/utils/ArrayUtils.java index 1402ad5e..b850ccc9 100644 --- a/src/main/java/com/gitblit/utils/ArrayUtils.java +++ b/src/main/java/com/gitblit/utils/ArrayUtils.java @@ -42,7 +42,7 @@ public class ArrayUtils { } public static boolean isEmpty(Collection collection) { - return collection == null || collection.size() == 0; + return collection == null || collection.isEmpty(); } public static String toString(Collection collection) { diff --git a/src/main/java/com/gitblit/utils/CommitCache.java b/src/main/java/com/gitblit/utils/CommitCache.java index a3963f50..53b8de19 100644 --- a/src/main/java/com/gitblit/utils/CommitCache.java +++ b/src/main/java/com/gitblit/utils/CommitCache.java @@ -19,9 +19,9 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import org.eclipse.jgit.lib.ObjectId; @@ -58,7 +58,7 @@ public class CommitCache { } protected CommitCache() { - cache = new ConcurrentHashMap>>(); + cache = new HashMap<>(); } /** @@ -93,7 +93,9 @@ public class CommitCache { * */ public void clear() { - cache.clear(); + synchronized (cache) { + cache.clear(); + } } /** @@ -103,8 +105,11 @@ public class CommitCache { */ public void clear(String repositoryName) { String repoKey = repositoryName.toLowerCase(); - ObjectCache> repoCache = cache.remove(repoKey); - if (repoCache != null) { + boolean hadEntries = false; + synchronized (cache) { + hadEntries = cache.remove(repoKey) != null; + } + if (hadEntries) { logger.info(MessageFormat.format("{0} commit cache cleared", repositoryName)); } } @@ -117,13 +122,17 @@ public class CommitCache { */ public void clear(String repositoryName, String branch) { String repoKey = repositoryName.toLowerCase(); - ObjectCache> repoCache = cache.get(repoKey); - if (repoCache != null) { - List commits = repoCache.remove(branch.toLowerCase()); - if (!ArrayUtils.isEmpty(commits)) { - logger.info(MessageFormat.format("{0}:{1} commit cache cleared", repositoryName, branch)); + boolean hadEntries = false; + synchronized (cache) { + ObjectCache> repoCache = cache.get(repoKey); + if (repoCache != null) { + List commits = repoCache.remove(branch.toLowerCase()); + hadEntries = !ArrayUtils.isEmpty(commits); } } + if (hadEntries) { + logger.info(MessageFormat.format("{0}:{1} commit cache cleared", repositoryName, branch)); + } } /** @@ -156,49 +165,55 @@ public class CommitCache { if (cacheDays > 0 && (sinceDate.getTime() >= cacheCutoffDate.getTime())) { // request fits within the cache window String repoKey = repositoryName.toLowerCase(); - if (!cache.containsKey(repoKey)) { - cache.put(repoKey, new ObjectCache>()); - } - - ObjectCache> repoCache = cache.get(repoKey); String branchKey = branch.toLowerCase(); RevCommit tip = JGitUtils.getCommit(repository, branch); Date tipDate = JGitUtils.getCommitDate(tip); - List commits; - if (!repoCache.hasCurrent(branchKey, tipDate)) { - commits = repoCache.getObject(branchKey); - if (ArrayUtils.isEmpty(commits)) { - // we don't have any cached commits for this branch, reload - commits = get(repositoryName, repository, branch, cacheCutoffDate); - repoCache.updateObject(branchKey, tipDate, commits); - logger.debug(MessageFormat.format("parsed {0} commits from {1}:{2} since {3,date,yyyy-MM-dd} in {4} msecs", - commits.size(), repositoryName, branch, cacheCutoffDate, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start))); - } else { - // incrementally update cache since the last cached commit - ObjectId sinceCommit = commits.get(0).getId(); - List incremental = get(repositoryName, repository, branch, sinceCommit); - logger.info(MessageFormat.format("incrementally added {0} commits to cache for {1}:{2} in {3} msecs", - incremental.size(), repositoryName, branch, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start))); - incremental.addAll(commits); - repoCache.updateObject(branchKey, tipDate, incremental); - commits = incremental; + ObjectCache> repoCache; + synchronized (cache) { + repoCache = cache.get(repoKey); + if (repoCache == null) { + repoCache = new ObjectCache<>(); + cache.put(repoKey, repoCache); } - } else { - // cache is current - commits = repoCache.getObject(branchKey); - // evict older commits outside the cache window - commits = reduce(commits, cacheCutoffDate); - // update cache - repoCache.updateObject(branchKey, tipDate, commits); } + synchronized (repoCache) { + List commits; + if (!repoCache.hasCurrent(branchKey, tipDate)) { + commits = repoCache.getObject(branchKey); + if (ArrayUtils.isEmpty(commits)) { + // we don't have any cached commits for this branch, reload + commits = get(repositoryName, repository, branch, cacheCutoffDate); + repoCache.updateObject(branchKey, tipDate, commits); + logger.debug(MessageFormat.format("parsed {0} commits from {1}:{2} since {3,date,yyyy-MM-dd} in {4} msecs", + commits.size(), repositoryName, branch, cacheCutoffDate, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start))); + } else { + // incrementally update cache since the last cached commit + ObjectId sinceCommit = commits.get(0).getId(); + List incremental = get(repositoryName, repository, branch, sinceCommit); + logger.info(MessageFormat.format("incrementally added {0} commits to cache for {1}:{2} in {3} msecs", + incremental.size(), repositoryName, branch, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start))); + incremental.addAll(commits); + repoCache.updateObject(branchKey, tipDate, incremental); + commits = incremental; + } + } else { + // cache is current + commits = repoCache.getObject(branchKey); + // evict older commits outside the cache window + commits = reduce(commits, cacheCutoffDate); + // update cache + repoCache.updateObject(branchKey, tipDate, commits); + } - if (sinceDate.equals(cacheCutoffDate)) { - list = commits; - } else { - // reduce the commits to those since the specified date - list = reduce(commits, sinceDate); + if (sinceDate.equals(cacheCutoffDate)) { + // Mustn't hand out the cached list; that's not thread-safe + list = new ArrayList<>(commits); + } else { + // reduce the commits to those since the specified date + list = reduce(commits, sinceDate); + } } logger.debug(MessageFormat.format("retrieved {0} commits from cache of {1}:{2} since {3,date,yyyy-MM-dd} in {4} msecs", list.size(), repositoryName, branch, sinceDate, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start))); @@ -222,8 +237,9 @@ public class CommitCache { */ protected List get(String repositoryName, Repository repository, String branch, Date sinceDate) { Map> allRefs = JGitUtils.getAllRefs(repository, false); - List commits = new ArrayList(); - for (RevCommit commit : JGitUtils.getRevLog(repository, branch, sinceDate)) { + List revLog = JGitUtils.getRevLog(repository, branch, sinceDate); + List commits = new ArrayList(revLog.size()); + for (RevCommit commit : revLog) { RepositoryCommit commitModel = new RepositoryCommit(repositoryName, branch, commit); List commitRefs = allRefs.get(commitModel.getId()); commitModel.setRefs(commitRefs); @@ -243,8 +259,9 @@ public class CommitCache { */ protected List get(String repositoryName, Repository repository, String branch, ObjectId sinceCommit) { Map> allRefs = JGitUtils.getAllRefs(repository, false); - List commits = new ArrayList(); - for (RevCommit commit : JGitUtils.getRevLog(repository, sinceCommit.getName(), branch)) { + List revLog = JGitUtils.getRevLog(repository, sinceCommit.getName(), branch); + List commits = new ArrayList(revLog.size()); + for (RevCommit commit : revLog) { RepositoryCommit commitModel = new RepositoryCommit(repositoryName, branch, commit); List commitRefs = allRefs.get(commitModel.getId()); commitModel.setRefs(commitRefs); @@ -261,7 +278,7 @@ public class CommitCache { * @return a list of commits */ protected List reduce(List commits, Date sinceDate) { - List filtered = new ArrayList(); + List filtered = new ArrayList(commits.size()); for (RepositoryCommit commit : commits) { if (commit.getCommitDate().compareTo(sinceDate) >= 0) { filtered.add(commit); -- cgit v1.2.3 From 4218f97ed40240c28d57ae8cb4f9e521d8a65ad3 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Tue, 18 Nov 2014 23:53:33 +0100 Subject: Improve logging when sending email fails. --- src/main/java/com/gitblit/service/MailService.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/service/MailService.java b/src/main/java/com/gitblit/service/MailService.java index ec3a84ca..58acc9c0 100644 --- a/src/main/java/com/gitblit/service/MailService.java +++ b/src/main/java/com/gitblit/service/MailService.java @@ -17,6 +17,7 @@ package com.gitblit.service; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Properties; @@ -31,6 +32,7 @@ import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; +import javax.mail.SendFailedException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; @@ -272,9 +274,22 @@ public class MailService implements Runnable { while ((message = queue.poll()) != null) { try { if (settings.getBoolean(Keys.mail.debug, false)) { - logger.info("send: " + StringUtils.trimString(message.getSubject(), 60)); + logger.info("send: '" + StringUtils.trimString(message.getSubject(), 60) + + "' to:" + StringUtils.trimString(Arrays.toString(message.getAllRecipients()), 300)); } Transport.send(message); + } catch (SendFailedException sfe) { + if (settings.getBoolean(Keys.mail.debug, false)) { + logger.error("Failed to send message: {}", sfe.getMessage()); + logger.info(" Invalid addresses: {}", Arrays.toString(sfe.getInvalidAddresses())); + logger.info(" Valid sent addresses: {}", Arrays.toString(sfe.getValidSentAddresses())); + logger.info(" Valid unset addresses: {}", Arrays.toString(sfe.getValidUnsentAddresses())); + logger.info("", sfe); + } + else { + logger.error("Failed to send message: {}", sfe.getMessage(), sfe.getNextException()); + } + failures.add(message); } catch (Throwable e) { logger.error("Failed to send message", e); failures.add(message); -- cgit v1.2.3 From 5c44219084e825feea72c60a83bc6889e3cf1bc9 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sat, 21 Jun 2014 02:53:21 +0200 Subject: Add integration strategy to merge tickes fast-forward or with commit. Add the option to merge a ticket branch to the integration branch only when it can be fast-forwarded, or always with a merge commit, or by fast-foward if possible, otherwise with a merge commit. Adds a new property ticket.mergeType with the valid values FAST_FOWARD_ONLY, MERGE_ALWAYS and MERGE_IF_NECESSARY. Merging and canMerge were refactored to make use of a new IntegrationStrategy class for each type of strategy. --- src/main/distrib/data/defaults.properties | 15 + src/main/java/com/gitblit/Constants.java | 31 ++ .../java/com/gitblit/git/PatchsetReceivePack.java | 3 +- .../com/gitblit/manager/RepositoryManager.java | 9 + .../java/com/gitblit/models/RepositoryModel.java | 3 + src/main/java/com/gitblit/utils/JGitUtils.java | 343 +++++++++++++++++---- .../java/com/gitblit/wicket/pages/TicketPage.java | 6 +- 7 files changed, 341 insertions(+), 69 deletions(-) (limited to 'src/main/java/com') diff --git a/src/main/distrib/data/defaults.properties b/src/main/distrib/data/defaults.properties index 0c7d6cd4..208fd992 100644 --- a/src/main/distrib/data/defaults.properties +++ b/src/main/distrib/data/defaults.properties @@ -567,6 +567,21 @@ tickets.acceptNewPatchsets = true # SINCE 1.4.0 tickets.requireApproval = false +# Default setting to control how patchsets are merged to the integration branch. +# Valid values: +# MERGE_ALWAYS - Always merge with a merge commit. Every ticket will show up as a branch, +# even if it could have been fast-forward merged. This is the default. +# MERGE_IF_NECESSARY - If possible, fast-forward the integration branch, +# if not, merge with a merge commit. +# FAST_FORWARD_ONLY - Only merge when a fast-forward is possible. This produces a strictly +# linear history of the integration branch. +# +# This setting can be overriden per-repository. +# +# RESTART REQUIRED +# SINCE 1.9.0 +tickets.mergeType = MERGE_ALWAYS + # The case-insensitive regular expression used to identify and close tickets on # push to the integration branch for commits that are NOT already referenced as # a patchset tip. diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 6232552e..321f84f9 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -639,6 +639,37 @@ public class Constants { } } + /** + * The type of merge Gitblit will use when merging a ticket to the integration branch. + *

+ * The default type is MERGE_ALWAYS. + *

+ * This is modeled after the Gerrit SubmitType. + */ + public static enum MergeType { + /** Allows a merge only if it can be fast-forward merged into the integration branch. */ + FAST_FORWARD_ONLY, + /** Uses a fast-forward merge if possible, other wise a merge commit is created. */ + MERGE_IF_NECESSARY, + // Future REBASE_IF_NECESSARY, + /** Always merge with a merge commit, even when a fast-forward would be possible. */ + MERGE_ALWAYS, + // Future? CHERRY_PICK + ; + + public static final MergeType DEFAULT_MERGE_TYPE = MERGE_ALWAYS; + + public static MergeType fromName(String name) { + for (MergeType type : values()) { + if (type.name().equalsIgnoreCase(name)) { + return type; + } + } + return DEFAULT_MERGE_TYPE; + } + } + + @Documented @Retention(RetentionPolicy.RUNTIME) public @interface Unused { diff --git a/src/main/java/com/gitblit/git/PatchsetReceivePack.java b/src/main/java/com/gitblit/git/PatchsetReceivePack.java index 33fa4705..4a09139a 100644 --- a/src/main/java/com/gitblit/git/PatchsetReceivePack.java +++ b/src/main/java/com/gitblit/git/PatchsetReceivePack.java @@ -599,7 +599,7 @@ public class PatchsetReceivePack extends GitblitReceivePack { } // ensure that the patchset can be cleanly merged right now - MergeStatus status = JGitUtils.canMerge(getRepository(), tipCommit.getName(), forBranch); + MergeStatus status = JGitUtils.canMerge(getRepository(), tipCommit.getName(), forBranch, repository.mergeType); switch (status) { case ALREADY_MERGED: sendError(""); @@ -1279,6 +1279,7 @@ public class PatchsetReceivePack extends GitblitReceivePack { getRepository(), patchset.tip, ticket.mergeTo, + getRepositoryModel().mergeType, committer, message); diff --git a/src/main/java/com/gitblit/manager/RepositoryManager.java b/src/main/java/com/gitblit/manager/RepositoryManager.java index e9bf5b84..baccfcfa 100644 --- a/src/main/java/com/gitblit/manager/RepositoryManager.java +++ b/src/main/java/com/gitblit/manager/RepositoryManager.java @@ -63,6 +63,7 @@ import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.Constants.AuthorizationControl; import com.gitblit.Constants.CommitMessageRenderer; import com.gitblit.Constants.FederationStrategy; +import com.gitblit.Constants.MergeType; import com.gitblit.Constants.PermissionType; import com.gitblit.Constants.RegistrantType; import com.gitblit.GitBlitException; @@ -899,6 +900,7 @@ public class RepositoryManager implements IRepositoryManager { model.acceptNewTickets = getConfig(config, "acceptNewTickets", true); model.requireApproval = getConfig(config, "requireApproval", settings.getBoolean(Keys.tickets.requireApproval, false)); model.mergeTo = getConfig(config, "mergeTo", null); + model.mergeType = MergeType.fromName(getConfig(config, "mergeType", settings.getString(Keys.tickets.mergeType, null))); model.useIncrementalPushTags = getConfig(config, "useIncrementalPushTags", false); model.incrementalPushTagPrefix = getConfig(config, "incrementalPushTagPrefix", null); model.allowForks = getConfig(config, "allowForks", true); @@ -1557,6 +1559,13 @@ public class RepositoryManager implements IRepositoryManager { if (!StringUtils.isEmpty(repository.mergeTo)) { config.setString(Constants.CONFIG_GITBLIT, null, "mergeTo", repository.mergeTo); } + if (repository.mergeType == null || repository.mergeType == MergeType.fromName(settings.getString(Keys.tickets.mergeType, null))) { + // use default + config.unset(Constants.CONFIG_GITBLIT, null, "mergeType"); + } else { + // override default + config.setString(Constants.CONFIG_GITBLIT, null, "mergeType", repository.mergeType.name()); + } config.setBoolean(Constants.CONFIG_GITBLIT, null, "useIncrementalPushTags", repository.useIncrementalPushTags); if (StringUtils.isEmpty(repository.incrementalPushTagPrefix) || repository.incrementalPushTagPrefix.equals(settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r"))) { diff --git a/src/main/java/com/gitblit/models/RepositoryModel.java b/src/main/java/com/gitblit/models/RepositoryModel.java index a81c622a..67ee1c7e 100644 --- a/src/main/java/com/gitblit/models/RepositoryModel.java +++ b/src/main/java/com/gitblit/models/RepositoryModel.java @@ -28,6 +28,7 @@ import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.Constants.AuthorizationControl; import com.gitblit.Constants.CommitMessageRenderer; import com.gitblit.Constants.FederationStrategy; +import com.gitblit.Constants.MergeType; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.ModelUtils; import com.gitblit.utils.StringUtils; @@ -89,6 +90,7 @@ public class RepositoryModel implements Serializable, Comparable Date: Mon, 23 Jun 2014 04:12:19 +0200 Subject: Add merge type setting to repository page. The merge type is a per repository setting. Add it to the edit page. --- src/main/java/com/gitblit/wicket/GitBlitWebApp.properties | 2 ++ src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html | 3 ++- src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index a215b4d6..b3cbef82 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -660,6 +660,7 @@ gb.nTotalTickets = {0} total gb.body = body gb.mergeSha = mergeSha gb.mergeTo = merge to +gb.mergeType = merge type gb.labels = labels gb.reviewers = reviewers gb.voters = voters @@ -671,6 +672,7 @@ gb.repositoryDoesNotAcceptPatchsets = This repository does not accept patchsets. gb.serverDoesNotAcceptPatchsets = This server does not accept patchsets. gb.ticketIsClosed = This ticket is closed. gb.mergeToDescription = default integration branch for merging ticket patchsets +gb.mergeTypeDescription = merge a ticket fast-forward only, if necessary, or always with a merge commit to the integration branch gb.anonymousCanNotPropose = Anonymous users can not propose patchsets. gb.youDoNotHaveClonePermission = You are not permitted to clone this repository. gb.myTickets = my tickets diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html index 7a55b9f5..2c881efc 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -123,7 +123,8 @@

- +
+ diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 6bcf6f51..bf3eea8b 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -56,6 +56,7 @@ import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.Constants.AuthorizationControl; import com.gitblit.Constants.CommitMessageRenderer; import com.gitblit.Constants.FederationStrategy; +import com.gitblit.Constants.MergeType; import com.gitblit.Constants.RegistrantType; import com.gitblit.GitBlitException; import com.gitblit.Keys; @@ -458,6 +459,11 @@ public class EditRepositoryPage extends RootSubPage { getString("gb.mergeToDescription"), new PropertyModel(repositoryModel, "mergeTo"), availableBranches)); + form.add(new ChoiceOption("mergeType", + getString("gb.mergeType"), + getString("gb.mergeTypeDescription"), + new PropertyModel(repositoryModel, "mergeType"), + Arrays.asList(MergeType.values()))); // // RECEIVE -- cgit v1.2.3 From d4a1aae48f097d48e9fded67445ba20720c1d966 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 31 Oct 2016 07:50:26 +0100 Subject: Fix disabled links in PagerPanel Disabled links in the PagerPanel (used on the LuceneSearchPage to page through search results) were only rendered as "disabled". The links themselves remained active, which gives strange effects when clicked. For instance it was possible to move to result pages -1, -2, and so on. Really disable the links. Add missing CSS rules to have correct styling as Wicket renders disabled links as spans, not anchors. Include the new CSS file in BasePage.html. And add the left/right arrows only if not on the first/last page. --- .../java/com/gitblit/wicket/pages/BasePage.html | 1 + .../java/com/gitblit/wicket/panels/PagerPanel.java | 5 +++-- src/main/resources/bootstrap-fixes.css | 25 ++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/bootstrap-fixes.css (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.html b/src/main/java/com/gitblit/wicket/pages/BasePage.html index b998428c..4dbc2e57 100644 --- a/src/main/java/com/gitblit/wicket/pages/BasePage.html +++ b/src/main/java/com/gitblit/wicket/pages/BasePage.html @@ -17,6 +17,7 @@ + diff --git a/src/main/java/com/gitblit/wicket/panels/PagerPanel.java b/src/main/java/com/gitblit/wicket/panels/PagerPanel.java index 2d774c41..d1214cae 100644 --- a/src/main/java/com/gitblit/wicket/panels/PagerPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/PagerPanel.java @@ -48,7 +48,7 @@ public class PagerPanel extends Panel { deltas = new int[] { -2, -1, 0, 1, 2 }; } - if (totalPages > 0) { + if (totalPages > 0 && currentPage > 1) { pages.add(new PageObject("\u2190", currentPage - 1)); } for (int delta : deltas) { @@ -57,7 +57,7 @@ public class PagerPanel extends Panel { pages.add(new PageObject("" + page, page)); } } - if (totalPages > 0) { + if (totalPages > 0 && currentPage < totalPages) { pages.add(new PageObject("\u2192", currentPage + 1)); } @@ -75,6 +75,7 @@ public class PagerPanel extends Panel { item.add(link); if (pageItem.page == currentPage || pageItem.page < 1 || pageItem.page > totalPages) { WicketUtils.setCssClass(item, "disabled"); + link.setEnabled(false); } } }; diff --git a/src/main/resources/bootstrap-fixes.css b/src/main/resources/bootstrap-fixes.css new file mode 100644 index 00000000..c9b6154b --- /dev/null +++ b/src/main/resources/bootstrap-fixes.css @@ -0,0 +1,25 @@ +/** + * Disabled links in a PagerPanel. Bootstrap 2.0.4 only handles , but not . Wicket renders disabled links as spans. + * The .pagination rules here are identical to the ones for in bootstrap.css, but for . + */ +.pagination span { + float: left; + padding: 0 14px; + line-height: 34px; + text-decoration: none; + border: 1px solid #ddd; + border-left-width: 0; +} + +.pagination li:first-child span { + border-left-width: 1px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.pagination li:last-child span { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} -- cgit v1.2.3 From a4ad77f9ec3292a7a6c2fb21689d672cf5db1f20 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Fri, 11 Nov 2016 19:22:17 +0100 Subject: Clean up `LdapAuthProvider` to properly cover different LDAP search scenarios. Gitblit allows in its configuration to set a "manager" user (and password) which can be used to search for the entry of a user wanting to log in. If they are both not set, an anonymous search is attempted. In the description below, when I say "...as manager", it is either as manager or anonymous. So far the behaviour of Gitblit, with respect to binding to and searching in LDAP, has been the following when a user logs in: **bind as manager** **search for the user** _bind as the user_ _search for the teams_ I'll call this code flow A. Later an additional configuration option had been added: `realm.ldap.bindpattern`. (PR gitblit/gitblit#162) It was meant to allow for not using a manager nor anonymous binds, by searching the directory as the user logging in. This is done in code flow B: **bind as manager** _bind as user_ _search for user_ _search for teams_ Both A and B are flawed, I think. In A, it looks like a mistake to me that the binding stays with the user after authentication. The problem that this causes is, that in LDAP server configurations where normal users are not allowed to read groups, the team information cannot be retrieved. I tried but failed to understand how B is supposed to work. There will always be a bind request as either anonymous or the manager DN when the LDAP connection is created. If neither is possible, the authentication process will fail and the user cannot log in. When synchronizing users and teams from LDAP, the following code flow is exercised: F: **bind as manager** **search for users** **search for teams** This patch fixes both code flows by introducing a new flow. C: **bind as manager** **search for user** _bind as user to authenticate_ **bind as manager** **search for teams** And it changes code flow B to the following code flow D: _bind as user_ _search for user_ _search for teams_ With code flows A, C, D and F the following usage (and authentication) scenarios are covered. They are described from the view of a Gitblit administrator's intent and his LDAP setup. * Users and team should be snychronized with LDAP This means anonymous or a fixed account must be able to read users and groups. => covered by C and F As the above allows for authentication and is required for synchronisation, all the others below do not cover synchronization. * No anonymous binding allowed and no special manager binding required This means that users must be able to read user an group entries. => covered by D * The user DN needs to be searched, e.g. because they are not all under the same parent DN. This means that anonymous or a fixed account must be able to read users. -- anonymous or the "manager" account can also read groups => covered by C -- anonymous or the "manager" account cannot read groups but a user can => covered by A I therefore believe that the new code will cover all common use cases. The implementation either directly binds as the user, when `bindpattern` is not empty, or it binds anonymous or against the manger DN to search for the user DN entry. If it directly bound against the user DN, the user is already authenticated. It will then only check that the user DN it found in the search is identical to the one it is currently bound against. If it was bound against a manager DN (or anonymously) it will bind against the found user DN to authenticate the user logging in, and will then rebind against the manager DN. When searching for groups in LDAP, if the search fails with a result code other than SUCCESS, the implementation will bind against the user DN, if it isn't already bound against it. It will then repeat the search for groups under the user authorization. This is to keep backwards compatible with the original behaviour A, in order to not break cases where the LDAP setup would deny a manager account to search for groups but allow it for normal users. To achieve this the implementation introduces an internal `LdapConnection` class that wraps the connection and keeps bind state, so that a rebind as a user is possible. This also fixes a resource leak where the connection was not closed in case that the initial bind as the manager account did not succeed. This commit would fix gitblit/gitblit#920 --- .../java/com/gitblit/auth/LdapAuthProvider.java | 398 +++++++++++++++------ 1 file changed, 284 insertions(+), 114 deletions(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/gitblit/auth/LdapAuthProvider.java b/src/main/java/com/gitblit/auth/LdapAuthProvider.java index cc772e7b..e1dec48f 100644 --- a/src/main/java/com/gitblit/auth/LdapAuthProvider.java +++ b/src/main/java/com/gitblit/auth/LdapAuthProvider.java @@ -39,6 +39,8 @@ import com.gitblit.service.LdapSyncService; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.StringUtils; import com.unboundid.ldap.sdk.Attribute; +import com.unboundid.ldap.sdk.BindRequest; +import com.unboundid.ldap.sdk.BindResult; import com.unboundid.ldap.sdk.DereferencePolicy; import com.unboundid.ldap.sdk.ExtendedResult; import com.unboundid.ldap.sdk.LDAPConnection; @@ -107,8 +109,14 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { if (enabled) { logger.info("Synchronizing with LDAP @ " + settings.getRequiredString(Keys.realm.ldap.server)); final boolean deleteRemovedLdapUsers = settings.getBoolean(Keys.realm.ldap.removeDeletedUsers, true); - LDAPConnection ldapConnection = getLdapConnection(); - if (ldapConnection != null) { + LdapConnection ldapConnection = new LdapConnection(); + if (ldapConnection.connect()) { + if (ldapConnection.bind() == null) { + ldapConnection.close(); + logger.error("Cannot synchronize with LDAP."); + return; + } + try { String accountBase = settings.getString(Keys.realm.ldap.accountBase, ""); String uidAttribute = settings.getString(Keys.realm.ldap.uid, "uid"); @@ -179,66 +187,6 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { } } - private LDAPConnection getLdapConnection() { - try { - - URI ldapUrl = new URI(settings.getRequiredString(Keys.realm.ldap.server)); - String ldapHost = ldapUrl.getHost(); - int ldapPort = ldapUrl.getPort(); - String bindUserName = settings.getString(Keys.realm.ldap.username, ""); - String bindPassword = settings.getString(Keys.realm.ldap.password, ""); - - LDAPConnection conn; - if (ldapUrl.getScheme().equalsIgnoreCase("ldaps")) { - // SSL - SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); - conn = new LDAPConnection(sslUtil.createSSLSocketFactory()); - if (ldapPort == -1) { - ldapPort = 636; - } - } else if (ldapUrl.getScheme().equalsIgnoreCase("ldap") || ldapUrl.getScheme().equalsIgnoreCase("ldap+tls")) { - // no encryption or StartTLS - conn = new LDAPConnection(); - if (ldapPort == -1) { - ldapPort = 389; - } - } else { - logger.error("Unsupported LDAP URL scheme: " + ldapUrl.getScheme()); - return null; - } - - conn.connect(ldapHost, ldapPort); - - if (ldapUrl.getScheme().equalsIgnoreCase("ldap+tls")) { - SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); - ExtendedResult extendedResult = conn.processExtendedOperation( - new StartTLSExtendedRequest(sslUtil.createSSLContext())); - if (extendedResult.getResultCode() != ResultCode.SUCCESS) { - throw new LDAPException(extendedResult.getResultCode()); - } - } - - if (StringUtils.isEmpty(bindUserName) && StringUtils.isEmpty(bindPassword)) { - // anonymous bind - conn.bind(new SimpleBindRequest()); - } else { - // authenticated bind - conn.bind(new SimpleBindRequest(bindUserName, bindPassword)); - } - - return conn; - - } catch (URISyntaxException e) { - logger.error("Bad LDAP URL, should be in the form: ldap(s|+tls)://:", e); - } catch (GeneralSecurityException e) { - logger.error("Unable to create SSL Connection", e); - } catch (LDAPException e) { - logger.error("Error Connecting to LDAP", e); - } - - return null; - } - /** * Credentials are defined in the LDAP server and can not be manipulated * from Gitblit. @@ -321,23 +269,26 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { public UserModel authenticate(String username, char[] password) { String simpleUsername = getSimpleUsername(username); - LDAPConnection ldapConnection = getLdapConnection(); - if (ldapConnection != null) { - try { - boolean alreadyAuthenticated = false; + LdapConnection ldapConnection = new LdapConnection(); + if (ldapConnection.connect()) { - String bindPattern = settings.getString(Keys.realm.ldap.bindpattern, ""); - if (!StringUtils.isEmpty(bindPattern)) { - try { - String bindUser = StringUtils.replace(bindPattern, "${username}", escapeLDAPSearchFilter(simpleUsername)); - ldapConnection.bind(bindUser, new String(password)); + // Try to bind either to the "manager" account, + // or directly to the DN of the user logging in, if realm.ldap.bindpattern is configured. + String passwd = new String(password); + BindResult bindResult = null; + String bindPattern = settings.getString(Keys.realm.ldap.bindpattern, ""); + if (! StringUtils.isEmpty(bindPattern)) { + bindResult = ldapConnection.bind(bindPattern, simpleUsername, passwd); + } else { + bindResult = ldapConnection.bind(); + } + if (bindResult == null) { + ldapConnection.close(); + return null; + } - alreadyAuthenticated = true; - } catch (LDAPException e) { - return null; - } - } + try { // Find the logging in user's DN String accountBase = settings.getString(Keys.realm.ldap.accountBase, ""); String accountPattern = settings.getString(Keys.realm.ldap.accountPattern, "(&(objectClass=person)(sAMAccountName=${username}))"); @@ -348,7 +299,7 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { SearchResultEntry loggingInUser = result.getSearchEntries().get(0); String loggingInUserDN = loggingInUser.getDN(); - if (alreadyAuthenticated || isAuthenticated(ldapConnection, loggingInUserDN, new String(password))) { + if (ldapConnection.isAuthenticated(loggingInUserDN, passwd)) { logger.debug("LDAP authenticated: " + username); UserModel user = null; @@ -462,7 +413,7 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { } } - private void getTeamsFromLdap(LDAPConnection ldapConnection, String simpleUsername, SearchResultEntry loggingInUser, UserModel user) { + private void getTeamsFromLdap(LdapConnection ldapConnection, String simpleUsername, SearchResultEntry loggingInUser, UserModel user) { String loggingInUserDN = loggingInUser.getDN(); // Clear the users team memberships - we're going to get them from LDAP @@ -479,7 +430,7 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { groupMemberPattern = StringUtils.replace(groupMemberPattern, "${" + userAttribute.getName() + "}", escapeLDAPSearchFilter(userAttribute.getValue())); } - SearchResult teamMembershipResult = doSearch(ldapConnection, groupBase, true, groupMemberPattern, Arrays.asList("cn")); + SearchResult teamMembershipResult = searchTeamsInLdap(ldapConnection, groupBase, true, groupMemberPattern, Arrays.asList("cn")); if (teamMembershipResult != null && teamMembershipResult.getEntryCount() > 0) { for (int i = 0; i < teamMembershipResult.getEntryCount(); i++) { SearchResultEntry teamEntry = teamMembershipResult.getSearchEntries().get(i); @@ -496,12 +447,12 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { } } - private void getEmptyTeamsFromLdap(LDAPConnection ldapConnection) { + private void getEmptyTeamsFromLdap(LdapConnection ldapConnection) { logger.info("Start fetching empty teams from ldap."); String groupBase = settings.getString(Keys.realm.ldap.groupBase, ""); String groupMemberPattern = settings.getString(Keys.realm.ldap.groupEmptyMemberPattern, "(&(objectClass=group)(!(member=*)))"); - SearchResult teamMembershipResult = doSearch(ldapConnection, groupBase, true, groupMemberPattern, null); + SearchResult teamMembershipResult = searchTeamsInLdap(ldapConnection, groupBase, true, groupMemberPattern, null); if (teamMembershipResult != null && teamMembershipResult.getEntryCount() > 0) { for (int i = 0; i < teamMembershipResult.getEntryCount(); i++) { SearchResultEntry teamEntry = teamMembershipResult.getSearchEntries().get(i); @@ -519,6 +470,30 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { logger.info("Finished fetching empty teams from ldap."); } + + private SearchResult searchTeamsInLdap(LdapConnection ldapConnection, String base, boolean dereferenceAliases, String filter, List attributes) { + SearchResult result = ldapConnection.search(base, dereferenceAliases, filter, attributes); + if (result == null) { + return null; + } + + if (result.getResultCode() != ResultCode.SUCCESS) { + // Retry the search with user authorization in case we searched as a manager account that could not search for teams. + logger.debug("Rebinding as user to search for teams in LDAP"); + result = null; + if (ldapConnection.rebindAsUser()) { + result = ldapConnection.search(base, dereferenceAliases, filter, attributes); + if (result.getResultCode() != ResultCode.SUCCESS) { + return null; + } + logger.info("Successful search after rebinding as user."); + } + } + + return result; + } + + private TeamModel createTeamFromLdap(SearchResultEntry teamEntry) { TeamModel answer = new TeamModel(teamEntry.getAttributeValue("cn")); answer.accountType = getAccountType(); @@ -527,47 +502,21 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { return answer; } - private SearchResult doSearch(LDAPConnection ldapConnection, String base, String filter) { - try { - return ldapConnection.search(base, SearchScope.SUB, filter); - } catch (LDAPSearchException e) { - logger.error("Problem Searching LDAP", e); - - return null; - } - } - - private SearchResult doSearch(LDAPConnection ldapConnection, String base, boolean dereferenceAliases, String filter, List attributes) { + private SearchResult doSearch(LdapConnection ldapConnection, String base, String filter) { try { SearchRequest searchRequest = new SearchRequest(base, SearchScope.SUB, filter); - if (dereferenceAliases) { - searchRequest.setDerefPolicy(DereferencePolicy.SEARCHING); - } - if (attributes != null) { - searchRequest.setAttributes(attributes); + SearchResult result = ldapConnection.search(searchRequest); + if (result.getResultCode() != ResultCode.SUCCESS) { + return null; } - return ldapConnection.search(searchRequest); - - } catch (LDAPSearchException e) { - logger.error("Problem Searching LDAP", e); - - return null; + return result; } catch (LDAPException e) { logger.error("Problem creating LDAP search", e); return null; } } - private boolean isAuthenticated(LDAPConnection ldapConnection, String userDn, String password) { - try { - // Binding will stop any LDAP-Injection Attacks since the searched-for user needs to bind to that DN - ldapConnection.bind(userDn, password); - return true; - } catch (LDAPException e) { - logger.error("Error authenticating user", e); - return false; - } - } + /** * Returns a simple username without any domain prefixes. @@ -585,7 +534,7 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { } // From: https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java - public static final String escapeLDAPSearchFilter(String filter) { + private static final String escapeLDAPSearchFilter(String filter) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < filter.length(); i++) { char curChar = filter.charAt(i); @@ -625,4 +574,225 @@ public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { } } + + + private class LdapConnection { + private LDAPConnection conn; + private SimpleBindRequest currentBindRequest; + private SimpleBindRequest managerBindRequest; + private SimpleBindRequest userBindRequest; + + + public LdapConnection() { + String bindUserName = settings.getString(Keys.realm.ldap.username, ""); + String bindPassword = settings.getString(Keys.realm.ldap.password, ""); + if (StringUtils.isEmpty(bindUserName) && StringUtils.isEmpty(bindPassword)) { + this.managerBindRequest = new SimpleBindRequest(); + } + this.managerBindRequest = new SimpleBindRequest(bindUserName, bindPassword); + } + + + boolean connect() { + try { + URI ldapUrl = new URI(settings.getRequiredString(Keys.realm.ldap.server)); + String ldapHost = ldapUrl.getHost(); + int ldapPort = ldapUrl.getPort(); + + if (ldapUrl.getScheme().equalsIgnoreCase("ldaps")) { + // SSL + SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); + conn = new LDAPConnection(sslUtil.createSSLSocketFactory()); + if (ldapPort == -1) { + ldapPort = 636; + } + } else if (ldapUrl.getScheme().equalsIgnoreCase("ldap") || ldapUrl.getScheme().equalsIgnoreCase("ldap+tls")) { + // no encryption or StartTLS + conn = new LDAPConnection(); + if (ldapPort == -1) { + ldapPort = 389; + } + } else { + logger.error("Unsupported LDAP URL scheme: " + ldapUrl.getScheme()); + return false; + } + + conn.connect(ldapHost, ldapPort); + + if (ldapUrl.getScheme().equalsIgnoreCase("ldap+tls")) { + SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); + ExtendedResult extendedResult = conn.processExtendedOperation( + new StartTLSExtendedRequest(sslUtil.createSSLContext())); + if (extendedResult.getResultCode() != ResultCode.SUCCESS) { + throw new LDAPException(extendedResult.getResultCode()); + } + } + + return true; + + } catch (URISyntaxException e) { + logger.error("Bad LDAP URL, should be in the form: ldap(s|+tls)://:", e); + } catch (GeneralSecurityException e) { + logger.error("Unable to create SSL Connection", e); + } catch (LDAPException e) { + logger.error("Error Connecting to LDAP", e); + } + + return false; + } + + + void close() { + if (conn != null) { + conn.close(); + } + } + + + SearchResult search(SearchRequest request) { + try { + return conn.search(request); + } catch (LDAPSearchException e) { + logger.error("Problem Searching LDAP [{}]", e.getResultCode()); + return e.getSearchResult(); + } + } + + + SearchResult search(String base, boolean dereferenceAliases, String filter, List attributes) { + try { + SearchRequest searchRequest = new SearchRequest(base, SearchScope.SUB, filter); + if (dereferenceAliases) { + searchRequest.setDerefPolicy(DereferencePolicy.SEARCHING); + } + if (attributes != null) { + searchRequest.setAttributes(attributes); + } + SearchResult result = search(searchRequest); + return result; + + } catch (LDAPException e) { + logger.error("Problem creating LDAP search", e); + return null; + } + } + + + + /** + * Bind using the manager credentials set in realm.ldap.username and ..password + * @return A bind result, or null if binding failed. + */ + BindResult bind() { + BindResult result = null; + try { + result = conn.bind(managerBindRequest); + currentBindRequest = managerBindRequest; + } catch (LDAPException e) { + logger.error("Error authenticating to LDAP with manager account to search the directory."); + logger.error(" Please check your settings for realm.ldap.username and realm.ldap.password."); + logger.debug(" Received exception when binding to LDAP", e); + return null; + } + return result; + } + + + /** + * Bind using the given credentials, by filling in the username in the given {@code bindPattern} to + * create the DN. + * @return A bind result, or null if binding failed. + */ + BindResult bind(String bindPattern, String simpleUsername, String password) { + BindResult result = null; + try { + String bindUser = StringUtils.replace(bindPattern, "${username}", escapeLDAPSearchFilter(simpleUsername)); + SimpleBindRequest request = new SimpleBindRequest(bindUser, password); + result = conn.bind(request); + userBindRequest = request; + currentBindRequest = userBindRequest; + } catch (LDAPException e) { + logger.error("Error authenticating to LDAP with user account to search the directory."); + logger.error(" Please check your settings for realm.ldap.bindpattern."); + logger.debug(" Received exception when binding to LDAP", e); + return null; + } + return result; + } + + + boolean rebindAsUser() { + if (userBindRequest == null || currentBindRequest == userBindRequest) { + return false; + } + try { + conn.bind(userBindRequest); + currentBindRequest = userBindRequest; + } catch (LDAPException e) { + conn.close(); + logger.error("Error rebinding to LDAP with user account.", e); + return false; + } + return true; + } + + + boolean isAuthenticated(String userDn, String password) { + verifyCurrentBinding(); + + // If the currently bound DN is already the DN of the logging in user, authentication has already happened + // during the previous bind operation. We accept this and return with the current bind left in place. + // This could also be changed to always retry binding as the logging in user, to make sure that the + // connection binding has not been tampered with in between. So far I see no way how this could happen + // and thus skip the repeated binding. + // This check also makes sure that the DN in realm.ldap.bindpattern actually matches the DN that was found + // when searching the user entry. + String boundDN = currentBindRequest.getBindDN(); + if (boundDN != null && boundDN.equals(userDn)) { + return true; + } + + // Bind a the logging in user to check for authentication. + // Afterwards, bind as the original bound DN again, to restore the previous authorization. + boolean isAuthenticated = false; + try { + // Binding will stop any LDAP-Injection Attacks since the searched-for user needs to bind to that DN + SimpleBindRequest ubr = new SimpleBindRequest(userDn, password); + conn.bind(ubr); + isAuthenticated = true; + userBindRequest = ubr; + } catch (LDAPException e) { + logger.error("Error authenticating user ({})", userDn, e); + } + + try { + conn.bind(currentBindRequest); + } catch (LDAPException e) { + logger.error("Error reinstating original LDAP authorization (code {}). Team information may be inaccurate for this log in.", + e.getResultCode(), e); + } + return isAuthenticated; + } + + + + private boolean verifyCurrentBinding() { + BindRequest lastBind = conn.getLastBindRequest(); + if (lastBind == currentBindRequest) { + return true; + } + logger.debug("Unexpected binding in LdapConnection. {} != {}", lastBind, currentBindRequest); + + String lastBoundDN = ((SimpleBindRequest)lastBind).getBindDN(); + String boundDN = currentBindRequest.getBindDN(); + logger.debug("Currently bound as '{}', check authentication for '{}'", lastBoundDN, boundDN); + if (boundDN != null && ! boundDN.equals(lastBoundDN)) { + logger.warn("Unexpected binding DN in LdapConnection. '{}' != '{}'.", lastBoundDN, boundDN); + logger.warn("Updated binding information in LDAP connection."); + currentBindRequest = (SimpleBindRequest)lastBind; + return false; + } + return true; + } + } } -- cgit v1.2.3 From 7f33a835295216210b7ca63367a460d76f9738d0 Mon Sep 17 00:00:00 2001 From: Martin Spielmann Date: Fri, 18 Nov 2016 23:31:27 +0100 Subject: Updated to latest wicket milestone and fix upgrade errors Some APIs changed like AjaxButton.onSubmit. All compile errors fixed and also RuntimeExceptions caused by wrong ajax event usages are resolved. --- build.moxie | 2 +- src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java | 4 ++-- src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java | 9 ++++++--- src/main/java/com/gitblit/wicket/pages/EditTicketPage.java | 6 ++++-- src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java | 2 +- src/main/java/com/gitblit/wicket/pages/NewTicketPage.java | 2 +- src/main/java/com/gitblit/wicket/pages/TicketPage.java | 4 ++-- src/main/java/com/gitblit/wicket/pages/UserPage.java | 2 +- src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.java | 2 +- src/main/java/com/gitblit/wicket/panels/BranchesPanel.java | 2 +- src/main/java/com/gitblit/wicket/panels/CommentPanel.java | 2 +- .../java/com/gitblit/wicket/panels/FederationProposalsPanel.java | 2 +- src/main/java/com/gitblit/wicket/panels/MarkdownTextArea.java | 6 +++--- .../com/gitblit/wicket/panels/RegistrantPermissionsPanel.java | 8 ++++---- src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java | 2 +- src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java | 2 +- src/main/java/com/gitblit/wicket/panels/TeamsPanel.java | 2 +- src/main/java/com/gitblit/wicket/panels/UsersPanel.java | 2 +- 18 files changed, 33 insertions(+), 28 deletions(-) (limited to 'src/main/java/com') diff --git a/build.moxie b/build.moxie index 1431e5ee..65ad9535 100644 --- a/build.moxie +++ b/build.moxie @@ -104,7 +104,7 @@ repositories: central, eclipse-snapshots, eclipse, gitblit properties: { jetty.version : 9.2.13.v20150730 slf4j.version : 1.7.12 - wicket.version : 7.4.0 + wicket.version : 8.0.0-M2 lucene.version : 4.10.4 jgit.version : 4.1.1.201511131810-r groovy.version : 2.4.4 diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java index ccb807c6..5ba57b40 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java @@ -120,7 +120,7 @@ public class EditMilestonePage extends RepositoryPage { private static final long serialVersionUID = 1L; @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { String name = nameModel.getObject(); if (StringUtils.isEmpty(name)) { return; @@ -180,7 +180,7 @@ public class EditMilestonePage extends RepositoryPage { } }; - delete.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( + delete.add(new JavascriptEventConfirmation("click", MessageFormat.format( getString("gb.deleteMilestone"), oldName))); form.add(delete); diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 61e6b0c9..a68f3d3e 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -28,6 +28,7 @@ import java.util.Set; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.AttributeModifier; +import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.extensions.markup.html.form.palette.Palette; @@ -369,8 +370,10 @@ public class EditRepositoryPage extends RootSubPage { // custom fields repositoryModel.customFields = new LinkedHashMap(); - for (int i = 0; i < customFieldsListView.size(); i++) { - ListItem child = (ListItem) customFieldsListView.get(i); + Iterator customFieldsListViewIterator = customFieldsListView.iterator(); + while(customFieldsListViewIterator.hasNext()){ + + ListItem child = (ListItem) customFieldsListViewIterator.next(); String key = child.getModelObject(); TextField field = (TextField) child.get("customFieldValue"); @@ -709,7 +712,7 @@ public class EditRepositoryPage extends RootSubPage { }; if (canDelete) { - delete.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( + delete.add(new JavascriptEventConfirmation("click", MessageFormat.format( getString("gb.deleteRepository"), repositoryModel))); } form.add(delete.setVisible(canDelete)); diff --git a/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java b/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java index 8cc2c611..b3be019b 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java @@ -62,7 +62,9 @@ import com.google.common.base.Optional; */ public class EditTicketPage extends RepositoryPage { - static final String NIL = ""; + private static final long serialVersionUID = 1L; + + static final String NIL = ""; static final String ESC_NIL = StringUtils.escapeForHtml(NIL, false); @@ -261,7 +263,7 @@ public class EditTicketPage extends RepositoryPage { private static final long serialVersionUID = 1L; @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { long ticketId = 0L; try { String h = WicketUtils.getObject(getPageParameters()); diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java index 833c6d47..f78b1c44 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java @@ -87,7 +87,7 @@ public class NewMilestonePage extends RepositoryPage { private static final long serialVersionUID = 1L; @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { String name = nameModel.getObject(); if (StringUtils.isEmpty(name)) { // invalid name diff --git a/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java b/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java index 1fd5839d..45478bc8 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java @@ -191,7 +191,7 @@ public class NewTicketPage extends RepositoryPage { private static final long serialVersionUID = 1L; @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { String title = titleModel.getObject(); if (StringUtils.isEmpty(title)) { return; diff --git a/src/main/java/com/gitblit/wicket/pages/TicketPage.java b/src/main/java/com/gitblit/wicket/pages/TicketPage.java index 290d6437..77d2236a 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/TicketPage.java @@ -1649,7 +1649,7 @@ public class TicketPage extends RepositoryPage { // javascript: manual copy & paste with modal browser prompt dialog Fragment copyFragment = new Fragment(wicketId, "jsPanel", TicketPage.this); ContextImage img = WicketUtils.newImage("copyIcon", "clippy.png"); - img.add(new JavascriptTextPrompt("onclick", "Copy to Clipboard (Ctrl+C, Enter)", text)); + img.add(new JavascriptTextPrompt("click", "Copy to Clipboard (Ctrl+C, Enter)", text)); copyFragment.add(img); return copyFragment; } @@ -1729,7 +1729,7 @@ public class TicketPage extends RepositoryPage { WicketUtils.setHtmlTooltip(deleteLink, MessageFormat.format(getString("gb.deletePatchset"), patchset.number)); - deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(getString("gb.deletePatchset"), patchset.number))); + deleteLink.add(new JavascriptEventConfirmation("click", MessageFormat.format(getString("gb.deletePatchset"), patchset.number))); return deleteLink; } diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index b37e75d8..8908016c 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -273,7 +273,7 @@ public class UserPage extends RootPage { private static final long serialVersionUID = 1L; @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { UserModel user = GitBlitWebSession.get().getUser(); diff --git a/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.java b/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.java index 9de3aa17..9c87a2a9 100644 --- a/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.java +++ b/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.java @@ -61,7 +61,7 @@ public class BooleanChoiceOption extends BasePanel { add(choice.setMarkupId("choice").setEnabled(choice.getChoices().size() > 0)); choice.setEnabled(checkbox.getModelObject()); - checkbox.add(new AjaxFormComponentUpdatingBehavior("onchange") { + checkbox.add(new AjaxFormComponentUpdatingBehavior("change") { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java b/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java index 92e7fb6d..a6ff921d 100644 --- a/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java @@ -236,7 +236,7 @@ public class BranchesPanel extends BasePanel { } }; - deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( + deleteLink.add(new JavascriptEventConfirmation("click", MessageFormat.format( "Delete branch \"{0}\"?", entry.displayName ))); return deleteLink; } diff --git a/src/main/java/com/gitblit/wicket/panels/CommentPanel.java b/src/main/java/com/gitblit/wicket/panels/CommentPanel.java index 3de07346..4740130a 100644 --- a/src/main/java/com/gitblit/wicket/panels/CommentPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/CommentPanel.java @@ -69,7 +69,7 @@ public class CommentPanel extends BasePanel { private static final long serialVersionUID = 1L; @Override - public void onSubmit(AjaxRequestTarget target, Form form) { + public void onSubmit(AjaxRequestTarget target) { String txt = markdownEditor.getText(); if (change == null) { // new comment diff --git a/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java b/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java index b02e848e..20d8a43c 100644 --- a/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java @@ -76,7 +76,7 @@ public class FederationProposalsPanel extends BasePanel { } } }; - deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( + deleteLink.add(new JavascriptEventConfirmation("click", MessageFormat.format( "Delete proposal \"{0}\"?", entry.name))); item.add(deleteLink); WicketUtils.setAlternatingBackground(item, counter); diff --git a/src/main/java/com/gitblit/wicket/panels/MarkdownTextArea.java b/src/main/java/com/gitblit/wicket/panels/MarkdownTextArea.java index f922686f..c3fce626 100644 --- a/src/main/java/com/gitblit/wicket/panels/MarkdownTextArea.java +++ b/src/main/java/com/gitblit/wicket/panels/MarkdownTextArea.java @@ -38,7 +38,7 @@ public class MarkdownTextArea extends TextArea { public MarkdownTextArea(String id, final IModel previewModel, final Label previewLabel) { super(id); setModel(new PropertyModel(this, "text")); - add(new AjaxFormComponentUpdatingBehavior("onblur") { + add(new AjaxFormComponentUpdatingBehavior("blur") { private static final long serialVersionUID = 1L; @Override @@ -49,7 +49,7 @@ public class MarkdownTextArea extends TextArea { } } }); - add(new AjaxFormComponentUpdatingBehavior("onchange") { + add(new AjaxFormComponentUpdatingBehavior("change") { private static final long serialVersionUID = 1L; @Override @@ -97,7 +97,7 @@ public class MarkdownTextArea extends TextArea { // private static final long serialVersionUID = 1L; // // public RichTextSetActiveTextFieldAttributeModifier(String markupId) { -// super("onClick", true, new Model("richTextSetActiveTextField('" + markupId + "');")); +// super("Click", true, new Model("richTextSetActiveTextField('" + markupId + "');")); // } // } diff --git a/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java b/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java index 839d80f9..ce288a84 100644 --- a/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java @@ -208,7 +208,7 @@ public class RegistrantPermissionsPanel extends BasePanel { permissionChoice.setEnabled(entry.mutable); permissionChoice.setOutputMarkupId(true); if (entry.mutable) { - permissionChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") { + permissionChoice.add(new AjaxFormComponentUpdatingBehavior("change") { private static final long serialVersionUID = 1L; @@ -254,9 +254,9 @@ public class RegistrantPermissionsPanel extends BasePanel { private static final long serialVersionUID = 1L; @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { // add permission to our list - RegistrantAccessPermission rp = (RegistrantAccessPermission) form.getModel().getObject(); + RegistrantAccessPermission rp = (RegistrantAccessPermission) getForm().getModel().getObject(); if (rp.permission == null) { return; } @@ -342,7 +342,7 @@ public class RegistrantPermissionsPanel extends BasePanel { } @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { RegistrantPermissionsPanel.this.activeState = buttonState; target.add(RegistrantPermissionsPanel.this); } diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java index 19fe46c1..262aa61a 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java @@ -359,7 +359,7 @@ public class RepositoryUrlPanel extends BasePanel { // javascript: manual copy & paste with modal browser prompt dialog Fragment copyFragment = new Fragment("copyFunction", "jsPanel", RepositoryUrlPanel.this); ContextImage img = WicketUtils.newImage("copyIcon", "clippy.png"); - img.add(new JavascriptTextPrompt("onclick", "Copy to Clipboard (Ctrl+C, Enter)", text)); + img.add(new JavascriptTextPrompt("click", "Copy to Clipboard (Ctrl+C, Enter)", text)); copyFragment.add(img); return copyFragment; } diff --git a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java index a06f9c4d..1ca3bb8a 100644 --- a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java @@ -123,7 +123,7 @@ public class SshKeysPanel extends BasePanel { private static final long serialVersionUID = 1L; @Override - protected void onSubmit(AjaxRequestTarget target, Form form) { + protected void onSubmit(AjaxRequestTarget target) { UserModel user = GitBlitWebSession.get().getUser(); String data = keyData.getObject(); diff --git a/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java b/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java index 69c64fc7..87e93e89 100644 --- a/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java @@ -83,7 +83,7 @@ public class TeamsPanel extends BasePanel { } } }; - deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( + deleteLink.add(new JavascriptEventConfirmation("click", MessageFormat.format( "Delete team \"{0}\"?", entry.name))); teamLinks.add(deleteLink); item.add(teamLinks); diff --git a/src/main/java/com/gitblit/wicket/panels/UsersPanel.java b/src/main/java/com/gitblit/wicket/panels/UsersPanel.java index 7200cb76..1a67bcb2 100644 --- a/src/main/java/com/gitblit/wicket/panels/UsersPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/UsersPanel.java @@ -103,7 +103,7 @@ public class UsersPanel extends BasePanel { } } }; - deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( + deleteLink.add(new JavascriptEventConfirmation("click", MessageFormat.format( getString("gb.deleteUser"), entry.username))); userLinks.add(deleteLink); item.add(userLinks); -- cgit v1.2.3