aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/layoutmgr/PageBreaker.java
blob: 299a537dc766189e02990567de22d9c3d4c1a69e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

package org.apache.fop.layoutmgr;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.apache.fop.area.Block;
import org.apache.fop.area.Footnote;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.RegionBody;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
import org.apache.fop.traits.MinOptMax;

/**
 * Handles the breaking of pages in an fo:flow
 */
public class PageBreaker extends AbstractBreaker {

    private PageSequenceLayoutManager pslm;
    private boolean firstPart = true;
    private boolean pageBreakHandled;
    private boolean needColumnBalancing;
    private PageProvider pageProvider;
    private Block separatorArea;

    /**
     * The FlowLayoutManager object, which processes
     * the single fo:flow of the fo:page-sequence
     */
    private FlowLayoutManager childFLM = null;

    private StaticContentLayoutManager footnoteSeparatorLM = null;

    public PageBreaker(PageSequenceLayoutManager pslm) {
        this.pslm = pslm;
        this.pageProvider = pslm.getPageProvider();
        this.childFLM = pslm.getLayoutManagerMaker().makeFlowLayoutManager(
                pslm, pslm.getPageSequence().getMainFlow());
    }

    /** {@inheritDoc} */
    protected void updateLayoutContext(LayoutContext context) {
        int flowIPD = pslm.getCurrentPV().getCurrentSpan().getColumnWidth();
        context.setRefIPD(flowIPD);
    }

    /** {@inheritDoc} */
    protected LayoutManager getTopLevelLM() {
        return pslm;
    }

    /** {@inheritDoc} */
    protected PageProvider getPageProvider() {
        return pslm.getPageProvider();
    }

    /** {@inheritDoc} */
    protected PageBreakingLayoutListener createLayoutListener() {
        return new PageBreakingLayoutListener() {

            public void notifyOverflow(int part, int amount, FObj obj) {
                Page p = pageProvider.getPage(
                            false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
                RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
                        Region.FO_REGION_BODY);
                BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
                        body.getUserAgent().getEventBroadcaster());

                boolean canRecover = (body.getOverflow() != Constants.EN_ERROR_IF_OVERFLOW);
                boolean needClip = (body.getOverflow() == Constants.EN_HIDDEN
                        || body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW);
                eventProducer.regionOverflow(this, body.getName(),
                        p.getPageViewport().getPageNumberString(),
                        amount, needClip, canRecover,
                        body.getLocator());
            }

        };
    }

    /** {@inheritDoc} */
    protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
        needColumnBalancing = false;
        if (childLC.getNextSpan() != Constants.NOT_SET) {
            //Next block list will have a different span.
            nextSequenceStartsOn = childLC.getNextSpan();
            needColumnBalancing = childLC.getNextSpan() == Constants.EN_ALL
                    && childLC.getDisableColumnBalancing() == Constants.EN_FALSE;

        }
        if (needColumnBalancing) {
            AbstractBreaker.log.debug(
                    "Column balancing necessary for the next element list!!!");
        }
        return nextSequenceStartsOn;
    }

    /** {@inheritDoc} */
    protected int getNextBlockList(LayoutContext childLC,
            int nextSequenceStartsOn) {
        if (!firstPart) {
            // if this is the first page that will be created by
            // the current BlockSequence, it could have a break
            // condition that must be satisfied;
            // otherwise, we may simply need a new page
            handleBreakTrait(nextSequenceStartsOn);
        }
        firstPart = false;
        pageBreakHandled = true;
        pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
                pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
        return super.getNextBlockList(childLC, nextSequenceStartsOn);
    }

    private boolean containsFootnotes(List contentList, LayoutContext context) {

        boolean containsFootnotes = false;
        if (contentList != null) {
            ListIterator contentListIterator = contentList.listIterator();
            while (contentListIterator.hasNext()) {
                ListElement element = (ListElement) contentListIterator.next();
                if (element instanceof KnuthBlockBox
                    && ((KnuthBlockBox) element).hasAnchors()) {
                    // element represents a line with footnote citations
                    containsFootnotes = true;
                    LayoutContext footnoteContext = new LayoutContext(context);
                    footnoteContext.setStackLimitBP(context.getStackLimitBP());
                    footnoteContext.setRefIPD(pslm.getCurrentPV()
                            .getRegionReference(Constants.FO_REGION_BODY).getIPD());
                    List footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
                    ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator();
                    // store the lists of elements representing the footnote bodies
                    // in the box representing the line containing their references
                    while (footnoteBodyIterator.hasNext()) {
                        FootnoteBodyLayoutManager fblm
                            = (FootnoteBodyLayoutManager) footnoteBodyIterator.next();
                        fblm.setParent(childFLM);
                        fblm.initialize();
                        ((KnuthBlockBox) element).addElementList(
                                fblm.getNextKnuthElements(footnoteContext, alignment));
                    }
                }
            }
        }
        return containsFootnotes;
    }

    private void handleFootnoteSeparator() {
        StaticContent footnoteSeparator;
        footnoteSeparator = pslm.getPageSequence().getStaticContent("xsl-footnote-separator");
        if (footnoteSeparator != null) {
            // the footnote separator can contain page-dependent content such as
            // page numbers or retrieve markers, so its areas cannot simply be
            // obtained now and repeated in each page;
            // we need to know in advance the separator bpd: the actual separator
            // could be different from page to page, but its bpd would likely be
            // always the same

            // create a Block area that will contain the separator areas
            separatorArea = new Block();
            separatorArea.setIPD(pslm.getCurrentPV()
                        .getRegionReference(Constants.FO_REGION_BODY).getIPD());
            // create a StaticContentLM for the footnote separator
            footnoteSeparatorLM
                    = pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
                        pslm, footnoteSeparator, separatorArea);
            footnoteSeparatorLM.doLayout();

            footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
        }
    }

    /** {@inheritDoc} */
    protected List getNextKnuthElements(LayoutContext context, int alignment) {
        List contentList = null;

        while (!childFLM.isFinished() && contentList == null) {
            contentList = childFLM.getNextKnuthElements(context, alignment);
        }

        // scan contentList, searching for footnotes
        if (containsFootnotes(contentList, context)) {
            // handle the footnote separator
            handleFootnoteSeparator();
        }
        return contentList;
    }

    /**
     * @return current display alignment
     */
    protected int getCurrentDisplayAlign() {
        return pslm.getCurrentPage().getSimplePageMaster().getRegion(
                Constants.FO_REGION_BODY).getDisplayAlign();
    }

    /**
     * @return whether or not this flow has more page break opportunities
     */
    protected boolean hasMoreContent() {
        return !childFLM.isFinished();
    }

    /**
     * Adds an area to the flow layout manager
     * @param posIter the position iterator
     * @param context the layout context
     */
    protected void addAreas(PositionIterator posIter, LayoutContext context) {
        if (footnoteSeparatorLM != null) {
            StaticContent footnoteSeparator = pslm.getPageSequence().getStaticContent(
                    "xsl-footnote-separator");
            // create a Block area that will contain the separator areas
            separatorArea = new Block();
            separatorArea.setIPD(
                    pslm.getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD());
            // create a StaticContentLM for the footnote separator
            footnoteSeparatorLM = (StaticContentLayoutManager)
                pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
                pslm, footnoteSeparator, separatorArea);
            footnoteSeparatorLM.doLayout();
        }

        childFLM.addAreas(posIter, context);
    }

    /**
     * {@inheritDoc}
     * This implementation checks whether to trigger column-balancing,
     * or whether to take into account a 'last-page' condition.
     */
    protected void doPhase3(PageBreakingAlgorithm alg, int partCount,
            BlockSequence originalList, BlockSequence effectiveList) {

        if (needColumnBalancing) {
            //column balancing for the last part
            doPhase3(alg, partCount, originalList, effectiveList, false);
            return;
        }

        boolean lastPageMasterDefined = pslm.getPageSequence().hasPagePositionLast();
        if (!hasMoreContent()) {
            //last part is reached
            if (lastPageMasterDefined) {
                //last-page condition
                doPhase3(alg, partCount, originalList, effectiveList, true);
                return;
            }
        }

        //nothing special: just add the areas now
        addAreas(alg, partCount, originalList, effectiveList);
    }

    /**
     * Restart the algorithm at the break corresponding
     * to the given partCount
     * (currently only used to redo the part after the
     *  last break in case of column-balancing
     *  and/or a last page-master)
     */
    private void doPhase3(PageBreakingAlgorithm alg, int partCount,
            BlockSequence originalList, BlockSequence effectiveList,
            boolean isLastPart) {


        int newStartPos = 0;
        int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
        if (restartPoint > 0) {
            //Add definitive areas for the parts before the
            //restarting point
            addAreas(alg, restartPoint, originalList, effectiveList);
            //Get page break from which we restart
            PageBreakPosition pbp = (PageBreakPosition)
                    alg.getPageBreaks().get(restartPoint - 1);
            newStartPos = pbp.getLeafPos() + 1;
            //Handle page break right here to avoid any side-effects
            if (newStartPos > 0) {
                handleBreakTrait(Constants.EN_PAGE);
            }
        }

        AbstractBreaker.log.debug("Restarting at " + restartPoint
                + ", new start position: " + newStartPos);

        pageBreakHandled = true;
        //Update so the available BPD is reported correctly
        int currentPageNum = pslm.getCurrentPageNum();
        pageProvider.setStartOfNextElementList(currentPageNum,
                pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());

        PageBreakingAlgorithm algRestart = null;
        int optimalPageCount;
        //Make sure we only add the areas we haven't added already
        effectiveList.ignoreAtStart = newStartPos;

        if (isLastPart) {
            pageProvider.setLastPageIndex(currentPageNum);
        }

        if (needColumnBalancing) {
            AbstractBreaker.log.debug("Column balancing now!!!");
            AbstractBreaker.log.debug("===================================================");

            //Restart last page
            algRestart = new BalancingColumnBreakingAlgorithm(
                    getTopLevelLM(), getPageProvider(), createLayoutListener(),
                    alignment, Constants.EN_START, footnoteSeparatorLength,
                    isPartOverflowRecoveryActivated(),
                    pslm.getCurrentPV().getBodyRegion().getColumnCount());
            AbstractBreaker.log.debug("===================================================");
        } else  {
            //plain last page, no column balancing
            AbstractBreaker.log.debug("Last page handling now!!!");
            AbstractBreaker.log.debug("===================================================");
            //Restart last page
            algRestart = new PageBreakingAlgorithm(
                    getTopLevelLM(), getPageProvider(), createLayoutListener(),
                    alg.getAlignment(), alg.getAlignmentLast(),
                    footnoteSeparatorLength,
                    isPartOverflowRecoveryActivated(), false, false);
            AbstractBreaker.log.debug("===================================================");
        }

        optimalPageCount = algRestart.findBreakingPoints(effectiveList,
                    newStartPos,
                    1, true, BreakingAlgorithm.ALL_BREAKS);
        AbstractBreaker.log.debug("restart: optimalPageCount= " + optimalPageCount
                + " pageBreaks.size()= " + algRestart.getPageBreaks().size());

        boolean fitsOnePage
                = optimalPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount();

        if (isLastPart) {
            if (fitsOnePage) {
                //Replace last page
                pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
            } else {
                //Last page-master cannot hold the content.
                //Add areas now...
                addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
                //...and add a blank last page
                pageProvider.setLastPageIndex(currentPageNum + 1);
                pslm.setCurrentPage(pslm.makeNewPage(true, true));
                return;
            }
        } else {
            if (!fitsOnePage) {
                AbstractBreaker.log.warn(
                        "Breaking algorithm produced more columns than are available.");
                /* reenable when everything works
                throw new IllegalStateException(
                        "Breaking algorithm must not produce more columns than available.");
                */
            }
        }

        addAreas(algRestart, optimalPageCount, originalList, effectiveList);
    }

    protected void startPart(BlockSequence list, int breakClass) {
        AbstractBreaker.log.debug("startPart() breakClass=" + breakClass);
        if (pslm.getCurrentPage() == null) {
            throw new IllegalStateException("curPage must not be null");
        }
        if (!pageBreakHandled) {

            //firstPart is necessary because we need the first page before we start the
            //algorithm so we have a BPD and IPD. This may subject to change later when we
            //start handling more complex cases.
            if (!firstPart) {
                // if this is the first page that will be created by
                // the current BlockSequence, it could have a break
                // condition that must be satisfied;
                // otherwise, we may simply need a new page
                handleBreakTrait(breakClass);
            }
            pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
                    pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
        }
        pageBreakHandled = false;
        // add static areas and resolve any new id areas
        // finish page and add to area tree
        firstPart = false;
    }

    /** {@inheritDoc} */
    protected void handleEmptyContent() {
        pslm.getCurrentPV().getPage().fakeNonEmpty();
    }

    protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
        // add footnote areas
        if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex
            || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) {
            // call addAreas() for each FootnoteBodyLM
            for (int i = pbp.footnoteFirstListIndex; i <= pbp.footnoteLastListIndex; i++) {
                List elementList = alg.getFootnoteList(i);
                int firstIndex = (i == pbp.footnoteFirstListIndex
                        ? pbp.footnoteFirstElementIndex : 0);
                int lastIndex = (i == pbp.footnoteLastListIndex
                        ? pbp.footnoteLastElementIndex : elementList.size() - 1);

                SpaceResolver.performConditionalsNotification(elementList,
                        firstIndex, lastIndex, -1);
                LayoutContext childLC = new LayoutContext(0);
                AreaAdditionUtil.addAreas(null,
                        new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1),
                        childLC);
            }
            // set the offset from the top margin
            Footnote parentArea = pslm.getCurrentPV().getBodyRegion().getFootnote();
            int topOffset = pslm.getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
            if (separatorArea != null) {
                topOffset -= separatorArea.getBPD();
            }
            parentArea.setTop(topOffset);
            parentArea.setSeparator(separatorArea);
        }
        pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished();
    }

    /**
     * @return the current child flow layout manager
     */
    protected LayoutManager getCurrentChildLM() {
        return childFLM;
    }

    /** {@inheritDoc} */
    protected void observeElementList(List elementList) {
        ElementListObserver.observe(elementList, "breaker",
                pslm.getFObj().getId());
    }

    /**
     * Depending on the kind of break condition, move to next column
     * or page. May need to make an empty page if next page would
     * not have the desired "handedness".
     * @param breakVal - value of break-before or break-after trait.
     */
    private void handleBreakTrait(int breakVal) {
        Page curPage = pslm.getCurrentPage();
        if (breakVal == Constants.EN_ALL) {
            //break due to span change in multi-column layout
            curPage.getPageViewport().createSpan(true);
            return;
        } else if (breakVal == Constants.EN_NONE) {
            curPage.getPageViewport().createSpan(false);
            return;
        } else if (breakVal == Constants.EN_COLUMN
                || breakVal <= 0
                || breakVal == Constants.EN_AUTO) {
            PageViewport pv = curPage.getPageViewport();

            //Check if previous page was spanned
            boolean forceNewPageWithSpan = false;
            RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
                    Constants.FO_REGION_BODY);
            if (breakVal < 0
                    && rb.getColumnCount() > 1
                    && pv.getCurrentSpan().getColumnCount() == 1) {
                forceNewPageWithSpan = true;
            }

            if (forceNewPageWithSpan) {
                curPage = pslm.makeNewPage(false, false);
                curPage.getPageViewport().createSpan(true);
            } else if (pv.getCurrentSpan().hasMoreFlows()) {
                pv.getCurrentSpan().moveToNextFlow();
            } else {
                curPage = pslm.makeNewPage(false, false);
            }
            return;
        }
        log.debug("handling break-before after page " + pslm.getCurrentPageNum()
            + " breakVal=" + breakVal);
        if (needBlankPageBeforeNew(breakVal)) {
            curPage = pslm.makeNewPage(true, false);
        }
        if (needNewPage(breakVal)) {
            curPage = pslm.makeNewPage(false, false);
        }
    }

    /**
     * Check if a blank page is needed to accomodate
     * desired even or odd page number.
     * @param breakVal - value of break-before or break-after trait.
     */
    private boolean needBlankPageBeforeNew(int breakVal) {
        if (breakVal == Constants.EN_PAGE || (pslm.getCurrentPage().getPageViewport().getPage().isEmpty())) {
            // any page is OK or we already have an empty page
            return false;
        } else {
            /* IF we are on the kind of page we need, we'll need a new page. */
            if (pslm.getCurrentPageNum() % 2 == 0) { // even page
                return (breakVal == Constants.EN_EVEN_PAGE);
            } else { // odd page
                return (breakVal == Constants.EN_ODD_PAGE);
            }
        }
    }

    /**
     * See if need to generate a new page
     * @param breakVal - value of break-before or break-after trait.
     */
    private boolean needNewPage(int breakVal) {
        if (pslm.getCurrentPage().getPageViewport().getPage().isEmpty()) {
            if (breakVal == Constants.EN_PAGE) {
                return false;
            } else if (pslm.getCurrentPageNum() % 2 == 0) { // even page
                return (breakVal == Constants.EN_ODD_PAGE);
            } else { // odd page
                return (breakVal == Constants.EN_EVEN_PAGE);
            }
        } else {
            return true;
        }
    }
}
27 Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
summaryrefslogtreecommitdiffstats
path: root/settings/l10n/zh_CN.js
blob: 9392b2d92e1250b9c7915039472e14111e0c2647 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
OC.L10N.register(
    "settings",
    {
    "Enabled" : "开启",
    "Not enabled" : "未启用",
    "Wrong password" : "密码错误",
    "Saved" : "已保存",
    "No user supplied" : "没有满足的用户",
    "Unable to change password" : "无法修改密码",
    "Authentication error" : "认证错误",
    "Please provide an admin recovery password, otherwise all user data will be lost" : "请提供管理员恢复密码, 否则所有用户的数据都将丢失.",
    "Wrong admin recovery password. Please check the password and try again." : "错误的管理员恢复密码. 请检查密码并重试.",
    "Backend doesn't support password change, but the user's encryption key was successfully updated." : "后端不支持修改密码, 但用户的加密密钥已成功更新.",
    "installing and updating apps via the app store or Federated Cloud Sharing" : "通过应用程序商店或联合云共享安装和更新应用程序",
    "Federated Cloud Sharing" : "联合云共享",
    "cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably." : "cURL 当前使用的过时 %s 的版本 (%s). 请更新你的操作系统或组件, 例如 %s 将无法可靠地工作.",
    "A problem occurred, please check your log files (Error: %s)" : "出现了问题, 请检查您的日志文件 (错误: %s)",
    "Migration Completed" : "迁移完成",
    "Group already exists." : "分组已经存在.",
    "Unable to add group." : "无法添加分组.",
    "Unable to delete group." : "无法删除分组.",
    "test email settings" : "测试电子邮件设置",
    "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "在发送电子邮件时出现问题. 请修正您的设置. (错误: %s)",
    "Email sent" : "邮件已发送",
    "You need to set your user email before being able to send test emails." : "在发送测试邮件前您需要设置您的电子邮件地址.",
    "Invalid request" : "无效请求",
    "Invalid mail address" : "无效的电子邮件地址",
    "No valid group selected" : "没有选择有效的分组",
    "A user with that name already exists." : "使用该名称的用户已存在.",
    "Unable to create user." : "无法创建用户.",
    "Your %s account was created" : "你的帐户 %s 已创建",
    "Unable to delete user." : "无法删除用户",
    "Settings saved" : "设置已保存",
    "Unable to change full name" : "无法修改全名",
    "Unable to change email address" : "无法修改电子邮箱地址",
    "Your full name has been changed." : "您的全名已修改.",
    "Forbidden" : "被禁止",
    "Invalid user" : "无效用户",
    "Unable to change mail address" : "无法修改电子邮箱地址",
    "Email saved" : "电子邮件已保存",
    "Password confirmation is required" : "需要密码确认",
    "Couldn't remove app." : "无法删除应用.",
    "Couldn't update app." : "无法更新应用.",
    "Are you really sure you want add {domain} as trusted domain?" : "您确定将 {domain} 添加为信任的域名么?",
    "Add trusted domain" : "添加信任域名",
    "Migration in progress. Please wait until the migration is finished" : "正在进行迁移. 请稍等, 直到迁移完成",
    "Migration started …" : "迁移开始...",
    "Not saved" : "未保存",
    "Sending..." : "正在发送...",
    "Official" : "官方",
    "All" : "全部",
    "Update to %s" : "更新为 %s",
    "_You have %n app update pending_::_You have %n app updates pending_" : ["%n 个应用正在等待升级"],
    "No apps found for your version" : "未找到适合当前版本的应用",
    "The app will be downloaded from the app store" : "该应用将从应用商店下载",
    "Official apps are developed by and within the community. They offer central functionality and are ready for production use." : "官方应用由社区和内部开发. 其可以提供核心功能并保证生产用途.",
    "Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "认证应用由值得信赖的开发者开发, 并通过了一个粗略的安全检查. 其在开放的代码库中活跃地维护, 他们的维护者认为在普通用途足够稳定.",
    "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "此应用没有检查安全问题, 它是新的或已知不稳定的. 安装风险自担.",
    "Enabling app …" : "正在启用应用程序...",
    "Error while disabling app" : "禁用应用时出错",
    "Disable" : "禁用",
    "Enable" : "启用",
    "Error while enabling app" : "启用应用时出错",
    "Error: this app cannot be enabled because it makes the server unstable" : "错误: 无法启用应用因为它会导致服务器不稳定",
    "Error: could not disable broken app" : "错误: 无法禁用损坏的应用",
    "Error while disabling broken app" : "禁用损坏的应用时出错",
    "Updating...." : "正在更新....",
    "Error while updating app" : "更新应用时出错",
    "Updated" : "已更新",
    "Uninstalling ...." : "正在卸载....",
    "Error while uninstalling app" : "卸载应用时发生了一个错误",
    "Uninstall" : "卸载",
    "The app has been enabled but needs to be updated. You will be redirected to the update page in 5 seconds." : "该应用已启用, 但是需要更新. 5秒后将跳转到更新页面.",
    "App update" : "更新应用",
    "Approved" : "已认证",
    "Experimental" : "实验",
    "No apps found for {query}" : "找不到符合 {query} 的应用",
    "Allow filesystem access" : "允许访问文件系统",
    "Disconnect" : "断开连接",
    "Revoke" : "撤销",
    "Internet Explorer" : "Internet Explorer",
    "Edge" : "Edge",
    "Firefox" : "Firefox",
    "Google Chrome" : "Google Chrome",
    "Safari" : "Safari",
    "Google Chrome for Android" : "Google Chrome for Android",
    "iPhone iOS" : "iPhone iOS",
    "iPad iOS" : "iPad iOS",
    "iOS Client" : "iOS 客户端",
    "Android Client" : "Android 客户端",
    "Sync client - {os}" : "同步客户端 - {os}",
    "This session" : "当前会话",
    "Copy" : "复制",
    "Copied!" : "已复制!",
    "Not supported!" : "不支持!",
    "Press ⌘-C to copy." : "按 ⌘-C 键复制.",
    "Press Ctrl-C to copy." : "按 Ctrl-C 复制.",
    "Error while loading browser sessions and device tokens" : "加载浏览器会话和设备令牌时出错",
    "Error while creating device token" : "创建设备令牌时出错",
    "Error while deleting the token" : "删除令牌时出错",
    "An error occurred. Please upload an ASCII-encoded PEM certificate." : "出现了一个错误. 请上传 ASCII 编码的 PEM 证书.",
    "Valid until {date}" : "有效期至 {date}",
    "Delete" : "删除",
    "Local" : "本地",
    "Private" : "私有",
    "Only visible to local users" : "仅对本地用户可见",
    "Only visible to you" : "仅您自己可见",
    "Contacts" : "联系人",
    "Visible to local users and to trusted servers" : "仅对本地用户和信任的服务器可见",
    "Public" : "公开",
    "Will be synced to a global and public address book" : "将同步到全局和公开地址簿中",
    "Select a profile picture" : "选择头像",
    "Very weak password" : "非常弱的密码",
    "Weak password" : "弱密码",
    "So-so password" : "一般强度的密码",
    "Good password" : "较强的密码",
    "Strong password" : "强密码",
    "Groups" : "分组",
    "Unable to delete {objName}" : "无法删除 {objName}",
    "Error creating group: {message}" : "创建分组时出错: {message}",
    "A valid group name must be provided" : "请提供一个有效的分组名称",
    "deleted {groupName}" : "已删除 {groupName}",
    "undo" : "撤销",
    "never" : "从不",
    "deleted {userName}" : "已删除 {userName}",
    "Unable to add user to group {group}" : "无法将用户添加到分组 {group}",
    "Unable to remove user from group {group}" : "无法从分组 {group} 中移除用户",
    "Add group" : "添加分组",
    "Invalid quota value \"{val}\"" : "无效的配额值 \"{val}\"",
    "no group" : "没有分组",
    "Password successfully changed" : "密码修改成功",
    "Changing the password will result in data loss, because data recovery is not available for this user" : "修改密码会导致数据丢失, 因为数据恢复不适用于此用户",
    "Could not change the users email" : "无法修改用户电子邮箱地址",
    "A valid username must be provided" : "必须提供合法的用户名",
    "Error creating user: {message}" : "创建用户出错: {message}",
    "A valid password must be provided" : "必须提供合法的密码",
    "A valid email must be provided" : "必须提供合法的用户名",
    "__language_name__" : "简体中文",
    "Unlimited" : "无限",
    "Personal info" : "个人信息",
    "Sessions" : "会话",
    "App passwords" : "应用密码",
    "Sync clients" : "同步客户端",
    "None" : "无",
    "Login" : "登录",
    "Plain" : "明文",
    "NT LAN Manager" : "NT LAN 管理器",
    "SSL/TLS" : "SSL/TLS",
    "STARTTLS" : "STARTTLS",
    "Email server" : "电子邮件服务器",
    "Open documentation" : "打开文档",
    "This is used for sending out notifications." : "这被用于发送通知.",
    "Send mode" : "发送模式",
    "Encryption" : "加密",
    "From address" : "来自地址",
    "mail" : "邮件",
    "Authentication method" : "认证方法",
    "Authentication required" : "需要认证",
    "Server address" : "服务器地址",
    "Port" : "端口",
    "Credentials" : "凭证",
    "SMTP Username" : "SMTP 用户名",
    "SMTP Password" : "SMTP 密码",
    "Store credentials" : "存储凭据",
    "Test email settings" : "测试电子邮件设置",
    "Send email" : "发送邮件",
    "Server-side encryption" : "服务器端加密",
    "Enable server-side encryption" : "启用服务器端加密",
    "Please read carefully before activating server-side encryption: " : "在激活服务器端加密之前, 请仔细阅读:",
    "Once encryption is enabled, all files uploaded to the server from that point forward will be encrypted at rest on the server. It will only be possible to disable encryption at a later date if the active encryption module supports that function, and all pre-conditions (e.g. setting a recover key) are met." : "一旦加密被启用, 之后上传到服务器的所有文件都将服务器上加密. 只有当启用状态的加密模块支持解密并且所有前提都满足时 (例如: 设定恢复密钥) 才能解除加密.",
    "Encryption alone does not guarantee security of the system. Please see documentation for more information about how the encryption app works, and the supported use cases." : "单独的加密不能保证系统的安全性. 请参考加密应用工作原理和支持的用例的文档获取更多信息",
    "Be aware that encryption always increases the file size." : "请注意, 加密会增加文件大小.",
    "It is always good to create regular backups of your data, in case of encryption make sure to backup the encryption keys along with your data." : "定期备份数据有助于保证数据完整, 并且确保备份您的加密数据和加密密钥.",
    "This is the final warning: Do you really want to enable encryption?" : "这是最后一次警告: 你确定要启用加密?",
    "Enable encryption" : "启用加密",
    "No encryption module loaded, please enable an encryption module in the app menu." : "没有加载加密模块, 请在 APP 应用菜单中启用加密模块.",
    "Select default encryption module:" : "选择默认的加密模块:",
    "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "您需要从旧版本 (ownCloud <= 8.0) 迁移您的加密密钥. 请在应用中启用 \\\"Default encryption module\\\" 并运行 'occ encryption:migrate'",
    "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "您需要从旧版本 (ownCloud<=8.0) 迁移您的加密密钥.",
    "Start migration" : "开始迁移",
    "Security & setup warnings" : "安全及设置警告",
    "php does not seem to be setup properly to query system environment variables. The test with getenv(\"PATH\") only returns an empty response." : "PHP 的设置似乎有问题, 无法获取系统环境变量. 使用 getenv(\\\"PATH\\\") 测试时仅返回空结果.",
    "Please check the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">installation documentation ↗</a> for php configuration notes and the php configuration of your server, especially when using php-fpm." : "请检查 <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">安装文档 ↗</a> 中关于 PHP 配置的说明并在您的服务器中进行配置, 尤其是使用 php-fpm 时.",
    "The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update." : "已启用只读配置. 这将阻止在 Web 界面中进行设置. 此外, 每次更新后该文件需要手动设置为可写入.",
    "PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "PHP 被设置为移除内联块, 这将导致多个核心应用无法访问.",
    "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "这可能是由缓存/加速器造成的, 例如 Zend OPcache 或 eAccelerator.",
    "Your database does not run with \"READ COMMITTED\" transaction isolation level. This can cause problems when multiple actions are executed in parallel." : "您的数据库不能在 \"READ COMMITTED\" 事务隔离级别运行. 这样可能导致在多个并行操作时出现问题.",
    "%1$s below version %2$s is installed, for stability and performance reasons we recommend updating to a newer %1$s version." : "已安装 %1$s 的低版本 %2$s. 出于稳定性和性能的原因, 我们建议您升级到更新的 %1$s 版本.",
    "The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "PHP 模块 'fileinfo' 缺失. 我们强烈建议启用此模块以便在 MIME 类型检测时获得最准确的结果.",
    "Transactional file locking is disabled, this might lead to issues with race conditions. Enable 'filelocking.enabled' in config.php to avoid these problems. See the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation ↗</a> for more information." : "事务文件锁被禁用, 这可能导致竞争条件的问题. 在 config.php 中启用 'filelocking.enabled' 选项来避免这些问题. 请参考 <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">文档↗</a> 获取更多信息.",
    "System locale can not be set to a one which supports UTF-8." : "系统区域无法设置为支持 UTF-8 的区域.",
    "This means that there might be problems with certain characters in file names." : "这意味着当文件名中包含特定字符时可能出现问题.",
    "We strongly suggest installing the required packages on your system to support one of the following locales: %s." : "我们强烈建议在您的系统中安装需要的包以支持下列区域: %s.",
    "If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "如果您不是安装在域名的根目录, 并且使用系统 cron 服务时, 可能导致 URL 生成问题. 为了避免这些问题, 请在您的 config.php 文件中设置 \"overwrite.cli.url\" 选项为您的安装根目录路径 (建议: \"%s\")",
    "It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "由于下列的技术错误, 无法通过 CLI 执行计划任务:",
    "Please double check the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"%s\">log</a>." : "请再次检查 <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">安装指南 ↗</a>, 并检查 <a href=\"%s\">日志</a> 中的任何错误或警告.",
    "All checks passed." : "所有检查已通过.",
    "Cron" : "计划任务",
    "Last cron job execution: %s." : "上次定时任务执行于: %s.",
    "Last cron job execution: %s. Something seems wrong." : "上次定时任务执行于: %s. 但存在一些问题.",
    "Cron was not executed yet!" : "定时任务还未被执行!",
    "Execute one task with each page loaded" : "每个页面加载后执行一个任务",
    "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php 注册到 webcron 服务上, 通过 http 每 15 分钟执行 cron.php.",
    "Use system's cron service to call the cron.php file every 15 minutes." : "使用系统 cron 服务每 15 分钟执行一次 cron.php 文件.",
    "The cron.php needs to be executed by the system user \"%s\"." : "cron.php 需要被系统用户 \"%s\" 执行.",
    "To run this you need the PHP posix extension. See {linkstart}PHP documentation{linkend} for more details." : "为了运行该功能, 您需要 PHP posix 扩展. 请参考 {linkstart}PHP 文档{linkend} 获取更多信息.",
    "Version" : "版本",
    "Sharing" : "共享",
    "Allow apps to use the Share API" : "允许应用使用共享 API",
    "Allow users to share via link" : "允许用户通过链接分享文件",
    "Allow public uploads" : "允许公开上传",
    "Enforce password protection" : "强制密码保护",
    "Set default expiration date" : "设置默认过期日期",
    "Expire after " : "过期于",
    "days" : "天",
    "Enforce expiration date" : "强制过期日期",
    "Allow resharing" : "允许二次共享",
    "Allow sharing with groups" : "允许群组共享",
    "Restrict users to only share with users in their groups" : "限制仅与组内用户分享",
    "Exclude groups from sharing" : "在分享中排除组",
    "These groups will still be able to receive shares, but not to initiate them." : "这些组将仍可以获取分享, 但无法向他人分享.",
    "Allow username autocompletion in share dialog. If this is disabled the full username needs to be entered." : "允许在共享对话框中自动补全用户名. 如果被禁用, 需要输入完整的用户名.",
    "Show disclaimer text on the public link upload page. (Only shown when the file list is hidden.)" : "在公开链接上传页中显示免责声明. (仅当文件列表隐藏时显示)",
    "This text will be shown on the public link upload page when the file list is hidden." : "这些内容将在公开链接上传页中当文件列表隐藏时显示.",
    "Tips & tricks" : "小提示",
    "SQLite is currently being used as the backend database. For larger installations we recommend that you switch to a different database backend." : "SQLite 当前被用作数据库. 对于较大数据量的安装和使用, 我们建议您切换到不同的数据库后端.",
    "This is particularly recommended when using the desktop client for file synchronisation." : "当时用桌面客户端同步文件时特别推荐.",
    "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation ↗</a>." : "合并其他数据库可以使用命令行工具:  'occ db:convert-type', 或查看 <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">文档 ↗</a>.",
    "How to do backups" : "如何备份",
    "Advanced monitoring" : "高级监控",
    "Performance tuning" : "性能优化",
    "Improving the config.php" : "优化 config.php",
    "Theming" : "主题",
    "Hardening and security guidance" : "强化和安全指南",
    "Developer documentation" : "开发者文档",
    "by %s" : "由 %s",
    "%s-licensed" : "%s-许可协议",
    "Documentation:" : "文档:",
    "User documentation" : "用户文档",
    "Admin documentation" : "管理员文档",
    "Visit website" : "访问网站",
    "Report a bug" : "报告问题",
    "Show description …" : "显示描述...",
    "Hide description …" : "隐藏描述...",
    "This app has an update available." : "此应用有可用的更新.",
    "This app has no minimum Nextcloud version assigned. This will be an error in the future." : "该应用没有指定支持的 Nextcloud 最低版本. 可能会在将来出现问题.",
    "This app has no maximum Nextcloud version assigned. This will be an error in the future." : "该应用没有指定支持的 Nextcloud 最高版本. 可能会在将来出现问题.",
    "This app cannot be installed because the following dependencies are not fulfilled:" : "无法安装应用, 因为无法满足下列依赖: ",
    "Enable only for specific groups" : "仅特定组启用",
    "Uninstall app" : "卸载应用",
    "SSL Root Certificates" : "SSL 根证书",
    "Common Name" : "通用名称",
    "Valid until" : "有效期至",
    "Issued By" : "授权由",
    "Valid until %s" : "有效期至 %s",
    "Import root certificate" : "导入根证书",
    "Hey there,<br><br>just letting you know that you now have a %s account.<br><br>Your username: <strong>%s</strong><br>Access it: <strong><a href=\"%s\">%s</a></strong><br><br>" : "您好,<br><br>您刚刚创建了 %s 账户<br><br>您的用户名: <strong>%s</strong><br>现在访问:  <strong><a href=\"%s\">%s</a></strong><br><br>",
    "Cheers!" : "干杯!",
    "Hey there,\n\njust letting you know that you now have a %s account.\n\nYour username: %s\nAccess it: %s\n\n" : "您好,\n\n您刚刚创建了 %s 账户.\n\n您的用户名: %s\n现在访问: %s\n",
    "Administrator documentation" : "管理员文档",
    "Online documentation" : "在线文档",
    "Forum" : "论坛",
    "Getting help" : "获取帮助",
    "Commercial support" : "商业支持",
    "You are using <strong>%s</strong> of <strong>%s</strong>" : "您正在使用 <strong>%s</strong> of <strong>%s</strong>",
    "Profile picture" : "账户头像",
    "Upload new" : "上传",
    "Select from Files" : "选择文件",
    "Remove image" : "删除图片",
    "png or jpg, max. 20 MB" : "png 或 jpg 格式, 不超过 20MB",
    "Picture provided by original account" : "原始账户图片",
    "Cancel" : "取消",
    "Choose as profile picture" : "选择个人头像",
    "Full name" : "全名",
    "No display name set" : "不显示名称设置",
    "Email" : "电子邮件",
    "Your email address" : "您的电子邮件",
    "No email address set" : "尚未设置 Email 地址",
    "For password recovery and notifications" : "用于密码恢复和通知",
    "Phone number" : "电话号码",
    "Your phone number" : "您的电话号码",
    "Address" : "地址",
    "Your postal address" : "您的邮寄地址",
    "Website" : "网站",
    "Your website" : "您的网站",
    "Twitter" : "Twitter",
    "Your Twitter handle" : "您的 Twitter 账号",
    "You are member of the following groups:" : "您是以下组的成员:",
    "Password" : "密码",
    "Current password" : "当前密码",
    "New password" : "新密码",
    "Change password" : "修改密码",
    "Language" : "语言",
    "Help translate" : "帮助翻译",
    "Get the apps to sync your files" : "下载应用同步您的文件",
    "Desktop client" : "桌面客户端",
    "Android app" : "Android 应用",
    "iOS app" : "iOS 应用",
    "If you want to support the project {contributeopen}join development{linkclose} or {contributeopen}spread the word{linkclose}!" : "如果您想支持这个项目 {contributeopen}一起开发{linkclose} 或 {contributeopen}帮助传播{linkclose}!",
    "Show First Run Wizard again" : "再次显示首次运行向导",
    "Web, desktop and mobile clients currently logged in to your account." : "您账号当前登录的 Web 页面, 桌面和客户端客户端.",
    "Device" : "设备",
    "Last activity" : "最后活跃",
    "Passcodes that give an app or device permissions to access your account." : "Passcodes 可以使应用或设备访问您的账号.",
    "Name" : "名称",
    "App name" : "应用名",
    "Create new app password" : "创建新应用密码",
    "Use the credentials below to configure your app or device." : "使用下述凭据配置您的应用或设备.",
    "For security reasons this password will only be shown once." : "由于安全原因, 密码仅会显示一次.",
    "Username" : "用户名",
    "Done" : "完成",
    "Developed by the {communityopen}Nextcloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}AGPL{linkclose}." : "由 {communityopen}Nextcloud community{linkclose} 开发, {githubopen}源代码{linkclose} 基于 {licenseopen}AGPL{linkclose} 许可协议.",
    "Follow us on Google Plus!" : "在 Google+ 上关注我们!",
    "Like our facebook page!" : "点赞我们 facebook 页面!",
    "Subscribe to our twitter channel!" : "关注我们的 twitter!",
    "Subscribe to our news feed!" : "订阅我们 RSS 最新消息!",
    "Subscribe to our newsletter!" : "订阅我们的最新消息!",
    "Show storage location" : "显示存储位置",
    "Show last log in" : "显示最后登录",
    "Show user backend" : "显示用户来源",
    "Send email to new user" : "发送电子邮件给新用户",
    "Show email address" : "显示邮件地址",
    "E-Mail" : "E-Mail",
    "Create" : "创建",
    "Admin Recovery Password" : "管理恢复密码",
    "Enter the recovery password in order to recover the users files during password change" : "输入恢复密码来在更改密码的时候恢复用户文件",
    "Group name" : "分组名",
    "Everyone" : "所有人",
    "Admins" : "管理员",
    "Default quota" : "默认配额",
    "Please enter storage quota (ex: \"512 MB\" or \"12 GB\")" : "请输入存储配额 (例如: \"512 MB\" 或 \"12 GB\")",
    "Other" : "其它",
    "Group admin for" : "分组管理员",
    "Quota" : "配额",
    "Storage location" : "存储位置",
    "User backend" : "用户来源",
    "Last login" : "最后登录",
    "change full name" : "更改全名",
    "set new password" : "设置新密码",
    "change email address" : "修改电子邮箱地址",
    "Default" : "默认",
    "log-level out of allowed range" : "日志级别超出允许的范围",
    "Language changed" : "语言已修改",
    "Admins can't remove themself from the admin group" : "管理员不能将自己移出管理组",
    "Unable to add user to group %s" : "无法将用户添加到分组 %s",
    "Unable to remove user from group %s" : "无法从分组 %s 中移除用户",
    "Are you really sure you want add \"{domain}\" as trusted domain?" : "您确定将 \"{domain}\" 添加为信任的域名么?",
    "Please wait...." : "请稍等....",
    "iPhone" : "iPhone",
    "add group" : "添加分组",
    "Everything (fatal issues, errors, warnings, info, debug)" : "全部 (灾难性问题, 错误, 警告, 信息, 调试)",
    "Info, warnings, errors and fatal issues" : "信息, 警告, 错误和灾难性问题",
    "Warnings, errors and fatal issues" : "警告, 错误和灾难性问题",
    "Errors and fatal issues" : "错误和灾难性问题",
    "Fatal issues only" : "仅灾难性问题",
    "Log" : "日志",
    "What to log" : "记录日志",
    "Download logfile" : "下载日志文件",
    "More" : "更多",
    "Less" : "更少",
    "The logfile is bigger than 100 MB. Downloading it may take some time!" : "日志文件超过了 100 MB. 下载可能需要一些时间!",
    "Allow users to send mail notification for shared files" : "允许用户发送共享文件的邮件通知",
    "Allow users to send mail notification for shared files to other users" : "允许用户发送共享文件的邮件通知给其他用户",
    "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite 被用作数据库. 对于较大数据量的安装和使用, 我们建议您切换到不同的数据库后端.",
    "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "特别当使用桌面客户端同步文件时, 不建议使用 SQLite.",
    "Experimental applications ahead" : "未来的实验应用",
    "Experimental apps are not checked for security issues, new or known to be unstable and under heavy development. Installing them can cause data loss or security breaches." : "实验性应用程序没有检查安全性问题, 它是新的或已知不稳定的. 安装它们可能会导致数据丢失或安全漏洞.",
    "Uninstall App" : "卸载应用",
    "Enable experimental apps" : "启用实验性应用程序",
    "Hey there,<br><br>just letting you know that you now have an %s account.<br><br>Your username: %s<br>Access it: <a href=\"%s\">%s</a><br><br>" : "亲,<br><br>现在我们为你开通了 %s 私有云帐户。<br><br>你的用户名: %s<br>访问网址: <a href=\\\"%s\\\">%s</a><br><br>",
    "Hey there,\n\njust letting you know that you now have an %s account.\n\nYour username: %s\nAccess it: %s\n\n" : "亲,\\n\\n 现在我们为你开通了 %s 私有去帐户。\\n\\n 你的用户名: %s\\n 访问网址: %s\\n 你的初始密码需要咨询系统管理员。或者你也可以在登录页面输入任意密码登录,\\n登录窗口将出现忘记密码链接,点击通过注册邮箱重设初始密码。\\n\\n",
    "If you want to support the project\n\t\t<a href=\"https://nextcloud.com/contribute\"\n\t\t\ttarget=\"_blank\" rel=\"noreferrer\">join development</a>\n\t\t<or></or>\n\t\t<a href=\"https://nextcloud.com/contribute\"\n\t\t\ttarget=\"_blank\" rel=\"noreferrer\">spread the word</a>!" : "如果您想支持这个项目\n\t<a href=\"https://nextcloud.com/contribute\" target=\"_blank\" rel=\"noreferrer\">一起开发</a>\n\t<or></or>\n\t<a href=\"https://nextcloud.com/contribute\" target=\"_blank\" rel=\"noreferrer\">帮助传播</a>!",
    "Add Group" : "添加分组",
    "Group" : "分组",
    "Default Quota" : "默认配额",
    "Full Name" : "全名",
    "Group Admin for" : "分组管理员",
    "Storage Location" : "存储位置",
    "User Backend" : "用户来源",
    "Last Login" : "最后登录"
},
"nplurals=1; plural=0;");