Merge pull request #1144 from fzs/logSendFailedException
Improve logging when sending email fails.
diff --git a/build.moxie b/build.moxie
index e1dbdd5..e84ab40 100644
--- a/build.moxie
+++ b/build.moxie
@@ -10,7 +10,7 @@
description: pure Java Git solution
groupId: com.gitblit
artifactId: gitblit
-version: 1.8.0
+version: 1.8.1-SNAPSHOT
inceptionYear: 2011
# Current stable release
diff --git a/releases.moxie b/releases.moxie
index 554028a..be1200e 100644
--- a/releases.moxie
+++ b/releases.moxie
@@ -1,4 +1,22 @@
#
+# ${project.version} release
+#
+r30: {
+ title: ${project.name} ${project.version} released
+ id: ${project.version}
+ date: ${project.buildDate}
+ note: ~
+ html: ~
+ text: ~
+ security: ~
+ fixes: ~
+ changes: ~
+ additions: ~
+ dependencyChanges: ~
+ contributors: ~
+}
+
+#
# 1.8.0 release
#
r29: {
@@ -1832,6 +1850,6 @@
- James Moger
}
-snapshot: ~
+snapshot: &r30
release: &r29
releases: &r[1..29]
diff --git a/src/main/distrib/data/defaults.properties b/src/main/distrib/data/defaults.properties
index 0c7d6cd..208fd99 100644
--- a/src/main/distrib/data/defaults.properties
+++ b/src/main/distrib/data/defaults.properties
@@ -567,6 +567,21 @@
# 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/distrib/data/groovy/sendmail-html.groovy b/src/main/distrib/data/groovy/sendmail-html.groovy
index 2692556..305c640 100644
--- a/src/main/distrib/data/groovy/sendmail-html.groovy
+++ b/src/main/distrib/data/groovy/sendmail-html.groovy
@@ -336,7 +336,7 @@
}
builder.td() {
mkp.yield header.oldPath
- mkp.yieldUnescaped "<b> -&rt; </b>"
+ mkp.yieldUnescaped "<b> -> </b>"
a(href:blobDiffUrl(id, header.newPath), header.newPath)
}
}
diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java
index 6232552..321f84f 100644
--- a/src/main/java/com/gitblit/Constants.java
+++ b/src/main/java/com/gitblit/Constants.java
@@ -639,6 +639,37 @@
}
}
+ /**
+ * The type of merge Gitblit will use when merging a ticket to the integration branch.
+ * <p>
+ * The default type is MERGE_ALWAYS.
+ * <p>
+ * 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 33fa470..4a09139 100644
--- a/src/main/java/com/gitblit/git/PatchsetReceivePack.java
+++ b/src/main/java/com/gitblit/git/PatchsetReceivePack.java
@@ -599,7 +599,7 @@
}
// 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 @@
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 e9bf5b8..2be6587 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.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 @@
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 @@
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"))) {
@@ -1952,39 +1961,47 @@
}
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();
- }
- }
- 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)));
+ 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();
+ }
+ }
+ 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/models/RepositoryModel.java b/src/main/java/com/gitblit/models/RepositoryModel.java
index a81c622..67ee1c7 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.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 boolean acceptNewTickets;
public boolean requireApproval;
public String mergeTo;
+ public MergeType mergeType;
public transient boolean isCollectingGarbage;
public Date lastGC;
@@ -111,6 +113,7 @@
this.isBare = true;
this.acceptNewTickets = true;
this.acceptNewPatchsets = true;
+ this.mergeType = MergeType.DEFAULT_MERGE_TYPE;
addOwner(owner);
}
diff --git a/src/main/java/com/gitblit/utils/ArrayUtils.java b/src/main/java/com/gitblit/utils/ArrayUtils.java
index 1402ad5..b850ccc 100644
--- a/src/main/java/com/gitblit/utils/ArrayUtils.java
+++ b/src/main/java/com/gitblit/utils/ArrayUtils.java
@@ -42,7 +42,7 @@
}
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 a3963f5..53b8de1 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.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 @@
}
protected CommitCache() {
- cache = new ConcurrentHashMap<String, ObjectCache<List<RepositoryCommit>>>();
+ cache = new HashMap<>();
}
/**
@@ -93,7 +93,9 @@
*
*/
public void clear() {
- cache.clear();
+ synchronized (cache) {
+ cache.clear();
+ }
}
/**
@@ -103,8 +105,11 @@
*/
public void clear(String repositoryName) {
String repoKey = repositoryName.toLowerCase();
- ObjectCache<List<RepositoryCommit>> 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 void clear(String repositoryName, String branch) {
String repoKey = repositoryName.toLowerCase();
- ObjectCache<List<RepositoryCommit>> repoCache = cache.get(repoKey);
- if (repoCache != null) {
- List<RepositoryCommit> 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<List<RepositoryCommit>> repoCache = cache.get(repoKey);
+ if (repoCache != null) {
+ List<RepositoryCommit> 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 @@
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<List<RepositoryCommit>>());
- }
-
- ObjectCache<List<RepositoryCommit>> repoCache = cache.get(repoKey);
String branchKey = branch.toLowerCase();
RevCommit tip = JGitUtils.getCommit(repository, branch);
Date tipDate = JGitUtils.getCommitDate(tip);
- List<RepositoryCommit> 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<RepositoryCommit> 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<List<RepositoryCommit>> 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<RepositoryCommit> 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<RepositoryCommit> 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 @@
*/
protected List<RepositoryCommit> get(String repositoryName, Repository repository, String branch, Date sinceDate) {
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, false);
- List<RepositoryCommit> commits = new ArrayList<RepositoryCommit>();
- for (RevCommit commit : JGitUtils.getRevLog(repository, branch, sinceDate)) {
+ List<RevCommit> revLog = JGitUtils.getRevLog(repository, branch, sinceDate);
+ List<RepositoryCommit> commits = new ArrayList<RepositoryCommit>(revLog.size());
+ for (RevCommit commit : revLog) {
RepositoryCommit commitModel = new RepositoryCommit(repositoryName, branch, commit);
List<RefModel> commitRefs = allRefs.get(commitModel.getId());
commitModel.setRefs(commitRefs);
@@ -243,8 +259,9 @@
*/
protected List<RepositoryCommit> get(String repositoryName, Repository repository, String branch, ObjectId sinceCommit) {
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, false);
- List<RepositoryCommit> commits = new ArrayList<RepositoryCommit>();
- for (RevCommit commit : JGitUtils.getRevLog(repository, sinceCommit.getName(), branch)) {
+ List<RevCommit> revLog = JGitUtils.getRevLog(repository, sinceCommit.getName(), branch);
+ List<RepositoryCommit> commits = new ArrayList<RepositoryCommit>(revLog.size());
+ for (RevCommit commit : revLog) {
RepositoryCommit commitModel = new RepositoryCommit(repositoryName, branch, commit);
List<RefModel> commitRefs = allRefs.get(commitModel.getId());
commitModel.setRefs(commitRefs);
@@ -261,7 +278,7 @@
* @return a list of commits
*/
protected List<RepositoryCommit> reduce(List<RepositoryCommit> commits, Date sinceDate) {
- List<RepositoryCommit> filtered = new ArrayList<RepositoryCommit>();
+ List<RepositoryCommit> filtered = new ArrayList<RepositoryCommit>(commits.size());
for (RepositoryCommit commit : commits) {
if (commit.getCommitDate().compareTo(sinceDate) >= 0) {
filtered.add(commit);
diff --git a/src/main/java/com/gitblit/utils/JGitUtils.java b/src/main/java/com/gitblit/utils/JGitUtils.java
index a02fc3f..0eea1d6 100644
--- a/src/main/java/com/gitblit/utils/JGitUtils.java
+++ b/src/main/java/com/gitblit/utils/JGitUtils.java
@@ -99,6 +99,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.gitblit.Constants.MergeType;
import com.gitblit.GitBlitException;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
@@ -2453,44 +2454,13 @@
* @param repository
* @param src
* @param toBranch
+ * @param mergeType
+ * Defines the integration strategy to use for merging.
* @return true if we can merge without conflict
*/
- public static MergeStatus canMerge(Repository repository, String src, String toBranch) {
- RevWalk revWalk = null;
- try {
- revWalk = new RevWalk(repository);
- ObjectId branchId = repository.resolve(toBranch);
- if (branchId == null) {
- return MergeStatus.MISSING_INTEGRATION_BRANCH;
- }
- ObjectId srcId = repository.resolve(src);
- if (srcId == null) {
- return MergeStatus.MISSING_SRC_BRANCH;
- }
- RevCommit branchTip = revWalk.lookupCommit(branchId);
- RevCommit srcTip = revWalk.lookupCommit(srcId);
- if (revWalk.isMergedInto(srcTip, branchTip)) {
- // already merged
- return MergeStatus.ALREADY_MERGED;
- } else if (revWalk.isMergedInto(branchTip, srcTip)) {
- // fast-forward
- return MergeStatus.MERGEABLE;
- }
- RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
- boolean canMerge = merger.merge(branchTip, srcTip);
- if (canMerge) {
- return MergeStatus.MERGEABLE;
- }
- } catch (NullPointerException e) {
- LOGGER.error("Failed to determine canMerge", e);
- } catch (IOException e) {
- LOGGER.error("Failed to determine canMerge", e);
- } finally {
- if (revWalk != null) {
- revWalk.close();
- }
- }
- return MergeStatus.NOT_MERGEABLE;
+ public static MergeStatus canMerge(Repository repository, String src, String toBranch, MergeType mergeType) {
+ IntegrationStrategy strategy = IntegrationStrategyFactory.create(mergeType, repository, src, toBranch);
+ return strategy.canMerge();
}
@@ -2511,11 +2481,13 @@
* @param repository
* @param src
* @param toBranch
+ * @param mergeType
+ * Defines the integration strategy to use for merging.
* @param committer
* @param message
* @return the merge result
*/
- public static MergeResult merge(Repository repository, String src, String toBranch,
+ public static MergeResult merge(Repository repository, String src, String toBranch, MergeType mergeType,
PersonIdent committer, String message) {
if (!toBranch.startsWith(Constants.R_REFS)) {
@@ -2523,15 +2495,202 @@
toBranch = Constants.R_HEADS + toBranch;
}
- RevWalk revWalk = null;
+ IntegrationStrategy strategy = IntegrationStrategyFactory.create(mergeType, repository, src, toBranch);
+ MergeResult mergeResult = strategy.merge(committer, message);
+
+ if (mergeResult.status != MergeStatus.MERGED) {
+ return mergeResult;
+ }
+
try {
- revWalk = new RevWalk(repository);
- RevCommit branchTip = revWalk.lookupCommit(repository.resolve(toBranch));
- RevCommit srcTip = revWalk.lookupCommit(repository.resolve(src));
- if (revWalk.isMergedInto(srcTip, branchTip)) {
- // already merged
- return new MergeResult(MergeStatus.ALREADY_MERGED, null);
+ // Update the integration branch ref
+ RefUpdate mergeRefUpdate = repository.updateRef(toBranch);
+ mergeRefUpdate.setNewObjectId(strategy.getMergeCommit());
+ mergeRefUpdate.setRefLogMessage(strategy.getRefLogMessage(), false);
+ mergeRefUpdate.setExpectedOldObjectId(strategy.branchTip);
+ RefUpdate.Result rc = mergeRefUpdate.update();
+ switch (rc) {
+ case FAST_FORWARD:
+ // successful, clean merge
+ break;
+ default:
+ mergeResult = new MergeResult(MergeStatus.FAILED, null);
+ throw new GitBlitException(MessageFormat.format("Unexpected result \"{0}\" when {1} in {2}",
+ rc.name(), strategy.getOperationMessage(), repository.getDirectory()));
}
+ } catch (IOException e) {
+ LOGGER.error("Failed to merge", e);
+ }
+
+ return mergeResult;
+ }
+
+
+ private static abstract class IntegrationStrategy {
+ Repository repository;
+ String src;
+ String toBranch;
+
+ RevWalk revWalk;
+ RevCommit branchTip;
+ RevCommit srcTip;
+
+ RevCommit mergeCommit;
+ String refLogMessage;
+ String operationMessage;
+
+ RevCommit getMergeCommit() {
+ return mergeCommit;
+ }
+
+ String getRefLogMessage() {
+ return refLogMessage;
+ }
+
+ String getOperationMessage() {
+ return operationMessage;
+ }
+
+ IntegrationStrategy(Repository repository, String src, String toBranch) {
+ this.repository = repository;
+ this.src = src;
+ this.toBranch = toBranch;
+ }
+
+ void prepare() throws IOException {
+ if (revWalk == null) revWalk = new RevWalk(repository);
+ ObjectId branchId = repository.resolve(toBranch);
+ if (branchId != null) {
+ branchTip = revWalk.lookupCommit(branchId);
+ }
+ ObjectId srcId = repository.resolve(src);
+ if (srcId != null) {
+ srcTip = revWalk.lookupCommit(srcId);
+ }
+ }
+
+
+ abstract MergeStatus _canMerge() throws IOException;
+
+
+ MergeStatus canMerge() {
+ try {
+ prepare();
+ if (branchTip == null) {
+ return MergeStatus.MISSING_INTEGRATION_BRANCH;
+ }
+ if (srcTip == null) {
+ return MergeStatus.MISSING_SRC_BRANCH;
+ }
+ if (revWalk.isMergedInto(srcTip, branchTip)) {
+ // already merged
+ return MergeStatus.ALREADY_MERGED;
+ }
+ // determined by specific integration strategy
+ return _canMerge();
+
+ } catch (NullPointerException e) {
+ LOGGER.error("Failed to determine canMerge", e);
+ } catch (IOException e) {
+ LOGGER.error("Failed to determine canMerge", e);
+ } finally {
+ if (revWalk != null) {
+ revWalk.close();
+ }
+ }
+
+ return MergeStatus.NOT_MERGEABLE;
+ }
+
+
+ abstract MergeResult _merge(PersonIdent committer, String message) throws IOException;
+
+
+ MergeResult merge(PersonIdent committer, String message) {
+ try {
+ prepare();
+ if (revWalk.isMergedInto(srcTip, branchTip)) {
+ // already merged
+ return new MergeResult(MergeStatus.ALREADY_MERGED, null);
+ }
+ // determined by specific integration strategy
+ return _merge(committer, message);
+
+ } catch (IOException e) {
+ LOGGER.error("Failed to merge", e);
+ } finally {
+ if (revWalk != null) {
+ revWalk.close();
+ }
+ }
+
+ return new MergeResult(MergeStatus.FAILED, null);
+ }
+ }
+
+
+ private static class FastForwardOnly extends IntegrationStrategy {
+ FastForwardOnly(Repository repository, String src, String toBranch) {
+ super(repository, src, toBranch);
+ }
+
+ @Override
+ MergeStatus _canMerge() throws IOException {
+ if (revWalk.isMergedInto(branchTip, srcTip)) {
+ // fast-forward
+ return MergeStatus.MERGEABLE;
+ }
+
+ return MergeStatus.NOT_MERGEABLE;
+ }
+
+ @Override
+ MergeResult _merge(PersonIdent committer, String message) throws IOException {
+ if (! revWalk.isMergedInto(branchTip, srcTip)) {
+ // is not fast-forward
+ return new MergeResult(MergeStatus.FAILED, null);
+ }
+
+ mergeCommit = srcTip;
+ refLogMessage = "merge " + src + ": Fast-forward";
+ operationMessage = MessageFormat.format("fast-forwarding {0} to commit {1}", srcTip.getName(), branchTip.getName());
+
+ return new MergeResult(MergeStatus.MERGED, srcTip.getName());
+ }
+ }
+
+ private static class MergeIfNecessary extends IntegrationStrategy {
+ MergeIfNecessary(Repository repository, String src, String toBranch) {
+ super(repository, src, toBranch);
+ }
+
+ @Override
+ MergeStatus _canMerge() throws IOException {
+ if (revWalk.isMergedInto(branchTip, srcTip)) {
+ // fast-forward
+ return MergeStatus.MERGEABLE;
+ }
+
+ RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
+ boolean canMerge = merger.merge(branchTip, srcTip);
+ if (canMerge) {
+ return MergeStatus.MERGEABLE;
+ }
+
+ return MergeStatus.NOT_MERGEABLE;
+ }
+
+ @Override
+ MergeResult _merge(PersonIdent committer, String message) throws IOException {
+ if (revWalk.isMergedInto(branchTip, srcTip)) {
+ // fast-forward
+ mergeCommit = srcTip;
+ refLogMessage = "merge " + src + ": Fast-forward";
+ operationMessage = MessageFormat.format("fast-forwarding {0} to commit {1}", branchTip.getName(), srcTip.getName());
+
+ return new MergeResult(MergeStatus.MERGED, srcTip.getName());
+ }
+
RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
boolean merged = merger.merge(branchTip, srcTip);
if (merged) {
@@ -2555,20 +2714,9 @@
ObjectId mergeCommitId = odi.insert(commitBuilder);
odi.flush();
- // set the merge ref to the merge commit
- RevCommit mergeCommit = revWalk.parseCommit(mergeCommitId);
- RefUpdate mergeRefUpdate = repository.updateRef(toBranch);
- mergeRefUpdate.setNewObjectId(mergeCommitId);
- mergeRefUpdate.setRefLogMessage("commit: " + mergeCommit.getShortMessage(), false);
- RefUpdate.Result rc = mergeRefUpdate.update();
- switch (rc) {
- case FAST_FORWARD:
- // successful, clean merge
- break;
- default:
- throw new GitBlitException(MessageFormat.format("Unexpected result \"{0}\" when merging commit {1} into {2} in {3}",
- rc.name(), srcTip.getName(), branchTip.getName(), repository.getDirectory()));
- }
+ mergeCommit = revWalk.parseCommit(mergeCommitId);
+ refLogMessage = "commit: " + mergeCommit.getShortMessage();
+ operationMessage = MessageFormat.format("merging commit {0} into {1}", srcTip.getName(), branchTip.getName());
// return the merge commit id
return new MergeResult(MergeStatus.MERGED, mergeCommitId.getName());
@@ -2576,17 +2724,82 @@
odi.close();
}
}
- } catch (IOException e) {
- LOGGER.error("Failed to merge", e);
- } finally {
- if (revWalk != null) {
- revWalk.close();
- }
+ return new MergeResult(MergeStatus.FAILED, null);
}
- return new MergeResult(MergeStatus.FAILED, null);
}
-
-
+
+ private static class MergeAlways extends IntegrationStrategy {
+ MergeAlways(Repository repository, String src, String toBranch) {
+ super(repository, src, toBranch);
+ }
+
+ @Override
+ MergeStatus _canMerge() throws IOException {
+ RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
+ boolean canMerge = merger.merge(branchTip, srcTip);
+ if (canMerge) {
+ return MergeStatus.MERGEABLE;
+ }
+
+ return MergeStatus.NOT_MERGEABLE;
+ }
+
+ @Override
+ MergeResult _merge(PersonIdent committer, String message) throws IOException {
+ RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
+ boolean merged = merger.merge(branchTip, srcTip);
+ if (merged) {
+ // create a merge commit and a reference to track the merge commit
+ ObjectId treeId = merger.getResultTreeId();
+ ObjectInserter odi = repository.newObjectInserter();
+ try {
+ // Create a commit object
+ CommitBuilder commitBuilder = new CommitBuilder();
+ commitBuilder.setCommitter(committer);
+ commitBuilder.setAuthor(committer);
+ commitBuilder.setEncoding(Constants.CHARSET);
+ if (StringUtils.isEmpty(message)) {
+ message = MessageFormat.format("merge {0} into {1}", srcTip.getName(), branchTip.getName());
+ }
+ commitBuilder.setMessage(message);
+ commitBuilder.setParentIds(branchTip.getId(), srcTip.getId());
+ commitBuilder.setTreeId(treeId);
+
+ // Insert the merge commit into the repository
+ ObjectId mergeCommitId = odi.insert(commitBuilder);
+ odi.flush();
+
+ mergeCommit = revWalk.parseCommit(mergeCommitId);
+ refLogMessage = "commit: " + mergeCommit.getShortMessage();
+ operationMessage = MessageFormat.format("merging commit {0} into {1}", srcTip.getName(), branchTip.getName());
+
+ // return the merge commit id
+ return new MergeResult(MergeStatus.MERGED, mergeCommitId.getName());
+ } finally {
+ odi.close();
+ }
+ }
+
+ return new MergeResult(MergeStatus.FAILED, null);
+ }
+ }
+
+
+ private static class IntegrationStrategyFactory {
+ static IntegrationStrategy create(MergeType mergeType, Repository repository, String src, String toBranch) {
+ switch(mergeType) {
+ case FAST_FORWARD_ONLY:
+ return new FastForwardOnly(repository, src, toBranch);
+ case MERGE_IF_NECESSARY:
+ return new MergeIfNecessary(repository, src, toBranch);
+ case MERGE_ALWAYS:
+ return new MergeAlways(repository, src, toBranch);
+ }
+ return null;
+ }
+ }
+
+
/**
* Returns the LFS URL for the given oid
* Currently assumes that the Gitblit Filestore is used
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
index a215b4d..b3cbef8 100644
--- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -660,6 +660,7 @@
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.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/GitBlitWebApp_nl.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties
index f43b8f5..f71d67d 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.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
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 16a9c86..bf2d2c3 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,783 @@
#!
-#! 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.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.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.canAdmin = \u53ef\u7ba1\u7406
-gb.canAdminDescription = \u53ef\u7ba1\u7406Gitblit\u4f3a\u670d\u5668
-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.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.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.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.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.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.ticketComments = \u8a3b\u89e3
+gb.view = \u6aa2\u8996
+gb.local = \u672c\u5730\u7aef
+gb.remote = \u9060\u7aef
+gb.branches = \u5206\u652f
+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 = \u8a73\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 = \u6587\u4ef6
+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 = \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)
+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.changePassword = \u4fee\u6539\u5bc6\u78bc
+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.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.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.users = \u4f7f\u7528\u8005
+gb.federation = federation
gb.error = \u932f\u8aa4
-gb.errorAdministrationDisabled = \u7ba1\u7406\u6b0a\u9650\u5df2\u53d6\u6d88
+gb.refresh = \u91cd\u6574
+gb.browse = \u700f\u89bd
+gb.clone = \u8907\u88fd(clone)
+gb.filter = \u7be9\u9078
+gb.create = \u5efa\u7acb
+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.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.<p/><p/>\u8a73\u60c5\u8acb\u53c3\u8003 <a target\ = "_new" href\ = "http\://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/queryparsersyntax.html">Lucene Query Parser Syntax</a>
+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.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 = \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)
+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(push)
+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.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.missingPermission = \u8a72\u6b0a\u9650\u7121\u6cd5\u5c0d\u61c9\u5230\u7248\u672c\u5eab!
+gb.mutable = \u52d5\u614b\u7d66\u4e88
+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.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\u884c<code>git clone</code>.\u5982\u679c\u4f60\u672c\u6a5f\u5df2\u6709\u6b64\u6587\u4ef6\u5eab\u4e14\u57f7\u884c\u904e<code>git init</code>,\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.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.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.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.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.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.newCertificate = \u5efa\u7acb\u8b49\u66f8
-gb.newCertificateDefaults = \u65b0\u8b49\u66f8\u9810\u8a2d\u503c
-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.nMoreCommits = \u9084\u6709{0}\u4efd\u63d0\u4ea4 \u00bb
-gb.noActivity = \u904e\u53bb{0}\u5929\u4f86,\u4e26\u6c92\u6709\u6d3b\u52d5\u7d00\u9304
-gb.noActivityToday = \u4eca\u5929\u6c92\u6709\u6d3b\u52d5\u7d00\u9304
-gb.noComments = \u6c92\u6709\u5099\u8a3b
-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.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.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.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.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,<em>\u4e26\u4e14\u5728refs\u5b8c\u7562\u5f8c</em>, \u5c07\u6703\u57f7\u884cPost-receive hook..<p>This is the appropriate hook for notifications, build triggers, etc.</p>
-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,<em>\u4f46\u5728\u9084\u6c92\u6709\u66f4\u65b0refs\u524d</em>, \u5c07\u6703\u57f7\u884cPre-receive hook. <p>This is the appropriate hook for rejecting a push.</p>
-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.<p/><p/>\u8a73\u60c5\u8acb\u53c3\u8003 <a target\ = "_new" href\ = "http\://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/queryparsersyntax.html">Lucene Query Parser Syntax</a>
-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.attributes = \u5c6c\u6027
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.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.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.sortMostPatchsetRevisions = \u6700\u591a\u88dc\u4e01\u4fee\u6b63
-gb.sortMostRecentlyUpdated = \u6700\u8fd1\u66f4\u65b0
-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.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 = \u5f9e
+gb.to = \u81f3
+gb.at = at
+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} \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
+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.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.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.updated = \u5df2\u66f4\u65b0
-gb.updatedBy = updated by
+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.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
+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.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.mergedPatchset = \u5c07\u88dc\u4e01\u5408\u4f75
+gb.commented = \u5df2\u8a3b\u89e3
+gb.noDescriptionGiven = \u6c92\u6709\u7d66\u4e88\u7c21\u8ff0
+gb.toBranch = \u5230\u5206\u652f {0}
+gb.createdBy = \u5efa\u7acb\u8005
+gb.oneParticipant = {0}\u53c3\u8207
+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 = {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
+gb.compareToN = \u8207{0}\u9032\u884c\u6bd4\u5c0d
+gb.open = \u958b\u555f
+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.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.sortNewest = \u6700\u65b0
+gb.sortOldest = \u6700\u820a
+gb.sortMostRecentlyUpdated = \u6700\u8fd1\u66f4\u65b0
+gb.sortLeastRecentlyUpdated = \u6700\u8fd1\u6700\u5c11\u8b8a\u52d5
+gb.sortMostComments = \u6700\u591a\u5099\u8a3b
+gb.sortLeastComments = \u6700\u5c11\u5099\u8a3b
+gb.sortMostPatchsetRevisions = \u6700\u591a\u88dc\u4e01\u4fee\u6b63
+gb.sortLeastPatchsetRevisions = \u6700\u5c11\u88dc\u4e01\u4fee\u6539
+gb.sortMostVotes = \u6700\u591a\u6295\u7968
+gb.sortLeastVotes = \u6700\u5c11\u6295\u7968
+gb.topicsAndLabels = \u8a71\u984c\u8207\u6a19\u8a18
+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.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.viewPolicy =
-gb.emailMeOnMyTicketChangesDescription =
+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 = \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
+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 = \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 = \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 = \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 = \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\u884c<code>git clone</code>.\u5982\u679c\u4f60\u672c\u6a5f\u5df2\u6709\u6b64\u7248\u672c\u5eab\u4e14\u57f7\u884c\u904e<code>git init</code>,\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,<em>\u4f46\u5728\u9084\u6c92\u6709\u66f4\u65b0refs\u524d</em>, \u5c07\u6703\u57f7\u884cPre-receive hook. <p>This is the appropriate hook for rejecting a push.</p>
+gb.postReceiveDescription = \u63a5\u5230\u63d0\u4ea4\u7533\u8acb\u5f8c,<em>\u4e26\u4e14\u5728refs\u5b8c\u7562\u5f8c</em>, \u5c07\u6703\u57f7\u884cPost-receive hook..<p>This is the appropriate hook for notifications, build triggers, etc.</p>
+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 =\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
+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.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.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.opacityAdjust = Adjust opacity
+gb.priority = \u512a\u5148
+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.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.
diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html
index 7a55b9f..2c881ef 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 @@
<div wicket:id="acceptNewTickets"></div>
<div wicket:id="requireApproval"></div>
<div wicket:id="mergeTo"></div>
-
+ <div wicket:id="mergeType"></div>
+
</div>
<!-- federation -->
diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java
index 6bcf6f5..bf3eea8 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.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 @@
getString("gb.mergeToDescription"),
new PropertyModel<String>(repositoryModel, "mergeTo"),
availableBranches));
+ form.add(new ChoiceOption<MergeType>("mergeType",
+ getString("gb.mergeType"),
+ getString("gb.mergeTypeDescription"),
+ new PropertyModel<MergeType>(repositoryModel, "mergeType"),
+ Arrays.asList(MergeType.values())));
//
// RECEIVE
diff --git a/src/main/java/com/gitblit/wicket/pages/TicketPage.java b/src/main/java/com/gitblit/wicket/pages/TicketPage.java
index cd049f4..e213396 100644
--- a/src/main/java/com/gitblit/wicket/pages/TicketPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/TicketPage.java
@@ -1405,14 +1405,14 @@
boolean allowMerge;
if (repository.requireApproval) {
- // rpeository requires approval
+ // repository requires approval
allowMerge = ticket.isOpen() && ticket.isApproved(patchset);
} else {
- // vetos are binding
+ // vetoes are binding
allowMerge = ticket.isOpen() && !ticket.isVetoed(patchset);
}
- MergeStatus mergeStatus = JGitUtils.canMerge(getRepository(), patchset.tip, ticket.mergeTo);
+ MergeStatus mergeStatus = JGitUtils.canMerge(getRepository(), patchset.tip, ticket.mergeTo, repository.mergeType);
if (allowMerge) {
if (MergeStatus.MERGEABLE == mergeStatus) {
// patchset can be cleanly merged to integration branch OR has already been merged
diff --git a/src/main/java/welcome_zh_TW.mkd b/src/main/java/welcome_zh_TW.mkd
index eaaee65..ec10201 100644
--- a/src/main/java/welcome_zh_TW.mkd
+++ b/src/main/java/welcome_zh_TW.mkd
@@ -1,3 +1,3 @@
## 歡迎來到Gitblit版本控管伺服器
-一個快速讓您能存放自己Git文件庫的解決方案 [Git](http://www.git-scm.com)
+一個快速讓您擁有版本控管伺服器的解決方案 : 使用[Git](http://www.git-scm.com)