diff --git a/Dockerfile b/Dockerfile
index bbb71bd5..8cbe4d7a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -364,7 +364,7 @@ COPY --from=prod-deps /src/packages/mcp/node_modules ./packages/mcp/node_modules
COPY --from=build /src/package.json ./package.json
COPY --from=build /src/apps/server/package.json ./apps/server/package.json
COPY --from=build /src/apps/server/dist ./apps/server/dist
-# The inventory report's fonts (D201): eight TTFs the server build converts from the @ibm/plex-*
+# The inventory report's fonts (D201): eleven TTFs the server build converts from the @ibm/plex-*
# devDependencies, with their OFL texts. dist/ already holds the report's child renderer and
# Typst template beside the modules that load them (src/reports/render/build-assets.ts).
COPY --from=build /src/apps/server/assets ./apps/server/assets
diff --git a/README.md b/README.md
index 0ef7831e..ff8ae905 100644
--- a/README.md
+++ b/README.md
@@ -136,9 +136,9 @@ Every feature, with its page: [all features](https://keptinventory.info/users/fe
CSV, full exports.
- **Your own network or HTTPS.** Works over plain http at home, with sign-ins as long as you set
and more than one address; an export with secret values needs HTTPS.
-- **Languages:** Arabic (right to left), English, French, German, Italian, Spanish, Ukrainian and
- Vietnamese; type to find yours, and amounts are read as your language writes them. The user,
- admin and install docs are in every language too.
+- **Languages:** Arabic (right to left), English, French, German, Italian, Simplified Chinese,
+ Spanish, Ukrainian and Vietnamese; type to find yours, and amounts are read as your language
+ writes them. The user, admin and install docs are in eight of those languages.
diff --git a/apps/docs/src/content/docs/developers/i18n-rtl.md b/apps/docs/src/content/docs/developers/i18n-rtl.md
index 5a0aa4c1..6d839b92 100644
--- a/apps/docs/src/content/docs/developers/i18n-rtl.md
+++ b/apps/docs/src/content/docs/developers/i18n-rtl.md
@@ -3,8 +3,8 @@ title: Languages and right-to-left
description: How strings are translated with Lingui, what the catalogue checks enforce, and the rules that keep Arabic correct.
---
-Kept ships in Arabic, English, French, German, Italian (D204), Spanish, Ukrainian and
-Vietnamese.
+Kept ships in Arabic, English, French, German, Italian (D204), Simplified Chinese, Spanish,
+Ukrainian and Vietnamese.
Arabic is right-to-left, so every screen has to mirror without per-screen overrides. The web app
uses [Lingui](https://lingui.dev/) with PO catalogues (D96); the server has its own small typed
tables for mail and reports.
@@ -12,7 +12,7 @@ tables for mail and reports.
## Lingui in the web app
`apps/web/lingui.config.ts` sets the source locale `en`, the locales `ar`, `de`, `en`, `es`, `fr`, `it`,
-`uk`, `vi`, and one catalogue per locale at `apps/web/src/locales//messages.po`, extracted from
+`uk`, `vi`, `zh`, and one catalogue per locale at `apps/web/src/locales//messages.po`, extracted from
`src` (tests and `routeTree.gen.ts` excluded). Catalogues have no line numbers, so they don't
churn on every edit.
diff --git a/apps/docs/src/content/docs/users/faq.md b/apps/docs/src/content/docs/users/faq.md
index 4712ef96..ae943188 100644
--- a/apps/docs/src/content/docs/users/faq.md
+++ b/apps/docs/src/content/docs/users/faq.md
@@ -110,8 +110,8 @@ no Kept needed. To bring Kept itself back on a new machine you also need the rec
## Which languages does it speak?
-Arabic (laid out right to left), English, French, German, Italian, Spanish, Ukrainian and
-Vietnamese, chosen per device. See [language and theme](/users/first-run/#6-language-and-theme).
+Arabic (laid out right to left), English, French, German, Italian, Simplified Chinese, Spanish,
+Ukrainian and Vietnamese, chosen per device. See [language and theme](/users/first-run/#6-language-and-theme).
## What licence is it under?
diff --git a/apps/docs/src/content/docs/users/features.md b/apps/docs/src/content/docs/users/features.md
index 65d65762..54dc36b9 100644
--- a/apps/docs/src/content/docs/users/features.md
+++ b/apps/docs/src/content/docs/users/features.md
@@ -79,10 +79,10 @@ a location turns them on in **Location settings → What to track**
network over plain http, [sign-ins as long as the admin sets](/install/home-network/#staying-on-your-network);
one Kept on [more than one address](/install/home-network/#more-than-one-address), such as a LAN
name and a Tailscale name.
-- **Languages**: Arabic (right to left), English, French, German, Italian, Spanish, Ukrainian
- and Vietnamese; type to find yours in the picker, and dates in your region's style, or as you choose.
+- **Languages**: Arabic (right to left), English, French, German, Italian, Simplified Chinese,
+ Spanish, Ukrainian and Vietnamese; type to find yours in the picker, and dates in your region's style, or as you choose.
Amounts are read as your language writes them. [PDFs](/users/reports/), claim packs and the readable copy
- come out in your language. The user, admin and install docs are in every language too.
+ come out in your language. The user, admin and install docs are in eight of those languages.
## On your phone
diff --git a/apps/server/package.json b/apps/server/package.json
index 97b657c1..17a1064a 100644
--- a/apps/server/package.json
+++ b/apps/server/package.json
@@ -82,6 +82,7 @@
"@ibm/plex-mono": "2.5.0",
"@ibm/plex-sans": "1.1.0",
"@ibm/plex-sans-arabic": "1.1.0",
+ "@ibm/plex-sans-sc": "1.1.0",
"@modelcontextprotocol/client": "2.3.1",
"@types/html-to-text": "9.0.4",
"@types/mailparser": "3.9.0",
diff --git a/apps/server/src/accounts/me.test.ts b/apps/server/src/accounts/me.test.ts
index 4cc286f2..3a71f94b 100644
--- a/apps/server/src/accounts/me.test.ts
+++ b/apps/server/src/accounts/me.test.ts
@@ -196,7 +196,7 @@ describe('GET /api/v1/me', () => {
).rowCount,
).toBe(1);
- for (const locale of ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi']) {
+ for (const locale of ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh']) {
const ok = await call(t, '/api/v1/me', { as: me, method: 'PATCH', body: { locale } });
expect(ok.statusCode, locale).toBe(200);
}
diff --git a/apps/server/src/assistant/prompt.test.ts b/apps/server/src/assistant/prompt.test.ts
index 092a0a53..60ef8808 100644
--- a/apps/server/src/assistant/prompt.test.ts
+++ b/apps/server/src/assistant/prompt.test.ts
@@ -91,7 +91,7 @@ describe('the tools as the model sees them', () => {
describe('the instructions', () => {
it("answer in each of Kept's languages", () => {
- expect(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'].map(languageOf)).toEqual([
+ expect(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'].map(languageOf)).toEqual([
'Arabic',
'German',
'English',
@@ -100,6 +100,7 @@ describe('the instructions', () => {
'Italian',
'Ukrainian',
'Vietnamese',
+ 'Simplified Chinese',
]);
});
diff --git a/apps/server/src/assistant/prompt.ts b/apps/server/src/assistant/prompt.ts
index 4d6e30dc..e537fe88 100644
--- a/apps/server/src/assistant/prompt.ts
+++ b/apps/server/src/assistant/prompt.ts
@@ -17,6 +17,7 @@ const LANGUAGES: Record = {
it: 'Italian',
uk: 'Ukrainian',
vi: 'Vietnamese',
+ zh: 'Simplified Chinese',
};
export type PromptLocation = { id: string; name: string; role: Role; canWrite: boolean };
diff --git a/apps/server/src/assistant/select.test.ts b/apps/server/src/assistant/select.test.ts
index 53b7b012..b814cdaa 100644
--- a/apps/server/src/assistant/select.test.ts
+++ b/apps/server/src/assistant/select.test.ts
@@ -381,6 +381,15 @@ describe('choosing the tools a step offers', () => {
expect(offered('Abre una reclamación'.normalize('NFD'))).toContain('open_claim');
});
+ it('matches Simplified Chinese questions without word spaces', () => {
+ expect(offered('把电钻借给 Louis 了')).toContain('lend_thing');
+ expect(offered('洗衣机的说明书和发票在哪')).toContain('find_documents');
+ expect(offered('卧室 4米乘3米')).toContain('create_place');
+ expect(offered('电池库存还剩多少')).toContain('adjust_stock');
+ expect(offered('汽车上次加油和保养记录')).toContain('log_fuel');
+ expect(offered('螺丝刀放在哪里?')).toEqual(offered('Are you working?'));
+ });
+
it('keeps a tool the thread already used, and one the model asked for and was not offered', () => {
expect(offered('and the drill?', ['lend_thing'])).toContain('lend_thing');
expect(offered('and the drill?', ['start_move'])).not.toContain('start_move');
diff --git a/apps/server/src/assistant/select.ts b/apps/server/src/assistant/select.ts
index 9cb0fae5..372be944 100644
--- a/apps/server/src/assistant/select.ts
+++ b/apps/server/src/assistant/select.ts
@@ -37,7 +37,7 @@ export const CORE_TOOLS: readonly ToolName[] = Object.freeze([
'mark_seen',
]);
-type Lang = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+type Lang = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
type Topic = { tools: readonly ToolName[]; words: Readonly> };
/** Keywords per topic and language, `|` between them, written plainly: `normalise` (or, for
@@ -60,6 +60,7 @@ const TOPICS: Readonly> = {
it: 'cronologia|storia|successo|chi ha',
uk: 'історі|сталос|трапил|хто перемі|хто перест|хто перен|хто пересун|хто змін|хто дода|коли$|востаннє|останній раз|минулого разу',
vi: 'lịch sử|đã xảy ra|chuyện gì|ai đã|ai chuyển|ai sửa|ai thêm|khi nào|lần cuối',
+ zh: '历史|记录|发生了什么|谁动过|谁移|谁改|谁加|什么时候|上次',
},
},
documents: {
@@ -73,6 +74,7 @@ const TOPICS: Readonly> = {
it: 'ricevuta|scontrino|fattura|manuale|documento|istruzioni',
uk: 'квитанці|чек$|чека$|чеку$|чеки$|чеків$|чеком$|рахунок|рахунк|фактур|інструкці|посібник|керівництв|документ|папери|паперів|пдф',
vi: 'hóa đơn|hoá đơn|biên lai|tài liệu|giấy tờ|chứng từ|hướng dẫn sử dụng|sách hướng dẫn',
+ zh: '收据|小票|发票|说明书|使用手册|手册|文档|证件|凭证',
},
},
// #313: changing a place (its name, kind, parent, order) and turning places into boxes.
@@ -88,6 +90,7 @@ const TOPICS: Readonly> = {
it: 'stanza|camera da letto|bagno|cucina|corridoio|soffitta|cantina|scaffal|cassetto|armadio|crea|collegamento|rinomin|in scatol|ordine|girare|giralo|girala|gira il|gira la|gira lo|ruotare|ruotalo|ruotala|di lato|sul fianco|mobil|libreria',
uk: 'кімната|кімнати|кімнату|кімнаті|кімнатою|кімнат$|спальня|спальню|спальні|спальнею|спалень|ванна|ванну|ванні|ванною|кухня|кухні|кухню|кухнею|вітальня|вітальні|вітальню|вітальнею|коридор|передпок|балкон|лоджі|горищ|підвал|льох|комор|полиц|поличк|поличц|шухляд|шафа|шафи|шафу|шафі|шафою|шаф$|шафк|шафц|комод|стелаж|гардероб|мебл|зона|зони|зону|зоні|зоною|місце$|місця$|місці$|місцем$|місць$|місцях$|приміщен|створ|фото$|фотограф|фотк|фоток|сфотограф|знімок|знімк|зображен|картинк|картинц|скану|відскан|посилан|лінк$|лінка$|лінку$|лінки$|прикріп|переймену|на коробк|на ящик|у коробк|в коробк|у ящик|в ящик|порядок$|власному порядку|упорядк|впорядк|перемісти вгору|перемісти вниз|перемісти вище|перемісти нижче|посунь вище|посунь нижче|розверн|розверт|оберн|оберт|на бік|набік|на боку|вертикально$|сторч|габарит',
vi: 'vị trí|phòng|kệ|giá sách|tủ quần áo|tủ sách|tủ đồ|ngăn kéo|nội thất|tạo|chụp|chụp ảnh|hình ảnh|quét|liên kết|đính kèm|đổi tên|thành hộp|thứ tự|xoay|nằm nghiêng|dựng đứng',
+ zh: '房间|卧室|厨房|卫生间|浴室|客厅|走廊|阳台|阁楼|地下室|置物架|书架|抽屉|橱柜|衣柜|书柜|家具|新建位置|创建房间|拍照|照片|扫码|链接|重命名|转为收纳箱|改成箱子|排序|上移|下移|旋转|侧放|横放|竖放|立起来',
},
},
schedules: {
@@ -101,6 +104,7 @@ const TOPICS: Readonly> = {
it: 'scadenz|scade|promemoria|manutenzion|presto|prossim|fatto|rimand|posticip|compito',
uk: 'термін$|терміну$|терміни$|терміном$|простроч|розклад$|розкладу$|розкладі$|розкладом$|графік$|графіку$|графіки$|графіком$|нагад|обслуговуван|найближч|наступн|скоро$|незабаром|невдовзі|сплив|закінчується|закінчиться|зроблено|викона|готово$|відклад|відклас|відстроч|пізніше|завдан|задач|цього тижня|цей тиждень|цьому тижні|цього місяця|цей місяць|цьому місяці',
vi: 'lịch trình|lịch bảo dưỡng|lịch hẹn|bảo dưỡng|bảo trì|đến hạn|quá hạn|nhắc|sắp tới|hết hạn|tiếp theo|xong|hoãn|dời|để sau|tác vụ|việc cần làm|tuần này|tháng này',
+ zh: '到期|逾期|过期|日程|计划|提醒|维护|即将|下一次|已完成|推迟|延后|待办|本周|这个月|本月',
},
},
lending: {
@@ -114,6 +118,7 @@ const TOPICS: Readonly> = {
it: 'prest|restitu|ridat|riavut|tornat|consegn|affidat',
uk: 'позич|запозич|одолж|борг|дав$|дала$|дали$|віддав|віддала$|віддали$|віддай|передав$|передала|передали|передати$|передай|передано|поверн|верну|назад$|забра|у кого|в кого|хто взяв|хто взяла|хто має|взяв у$|взяла у$|взяли у$|взяв в$|взяла в$|взяли в$',
vi: 'cho mượn|mượn|trả lại|đã trả|trả cho|trả về|lấy lại|nhận lại|ai đang giữ|ai giữ|đang giữ|bàn giao|giao cho',
+ zh: '借出|借给|借走|借用|借入|归还|还回|还给|拿回|在谁那|谁拿了|交接',
},
},
warranties: {
@@ -127,6 +132,7 @@ const TOPICS: Readonly> = {
it: 'garanzia|reclamo|riparazion|rotto|guasto',
uk: 'гаранті|рекламаці|претензі|страхов|ремонт|відремонт|полагод|лагод|злама|полама|розбит|розбив|розбил|несправн|дефект|не працює',
vi: 'bảo hành|yêu cầu bảo hành|sửa chữa|đi sửa|hỏng|hư|đổi trả',
+ zh: '保修|质保|联保|理赔|报修|维修|修理|坏了|故障|返修',
},
},
vehicles: {
@@ -140,6 +146,7 @@ const TOPICS: Readonly> = {
it: 'macchina|veicolo|tagliando|olio|gomm|chilometr|contachilometri|benzina|carburante|gasolio|pieno|lettura|contatore',
uk: 'автомобіл|авто$|автівк|автівц|транспортн|моя машин|мою машин|моєї машин|моїй машин|наша машин|нашу машин|нашої машин|на машині$|у машині$|в машині$|мотоцикл|скутер|мопед|велосипед|байк$|сервіс|техогляд|техобслугов|заміна масла|заміну масла|заміни масла|замінив масло|замінила масло|замінили масло|моторн|мастил|шина|шини|шину|шині|шин$|покришк|покришок|шиномонтаж|пробіг|одометр|спідометр|кілометр|км$|миль$|пальне|пального|пальним|пальному|бензин|бензобак|дизел|солярк|заправ|повний бак|лічильник|показання|показань|показник|мотогодин|електроенерг|кіловат|квт',
vi: 'xe|ô tô|phương tiện|bảo dưỡng|thay dầu|dầu|nhớt|lốp|số km|cây số|công tơ|công-tơ-mét|nhiên liệu|xăng|đổ xăng|đổ đầy|chỉ số|đồng hồ đo|đồng hồ điện|điện năng|kwh',
+ zh: '汽车|轿车|车辆|摩托|自行车|保养|机油|轮胎|里程|公里|汽油|柴油|加油|加满|充电|油箱|读数|表计|电表',
},
},
// #209: the tags themselves; tagging one thing is update_thing's, in the core.
@@ -154,6 +161,7 @@ const TOPICS: Readonly> = {
it: 'tag|etichetta',
uk: 'тег|протег|мітк|мітц|міток|ярлик|ярлич',
vi: 'gắn thẻ|bỏ thẻ|các thẻ|thẻ nào|thẻ này',
+ zh: '标签|打标签|取消标签',
},
},
stock: {
@@ -167,6 +175,7 @@ const TOPICS: Readonly> = {
it: 'scorta|scorte|rimast|esaurit|consumabil|usat|finit',
uk: 'запас$|запасу$|запаси$|запасів$|запасом$|запасах$|припас|залишилос|залишилас|залишилис|залишився|залишок|залишк|лишилос|лишилас|лишилис|лишився|закінч|скінч|вичерп|більше немає|немає більше|використав|використала|використали|використано|поповн|докуп|витратн|кількіст|кількост',
vi: 'tồn kho|còn lại|còn bao nhiêu|còn mấy|sắp hết|dùng hết|hết rồi|vật tư|tiêu hao|bổ sung|nạp thêm|mua thêm|số lượng',
+ zh: '库存|余量|还剩|用完|耗尽|快没了|补货|补充|耗材|数量',
},
},
};
@@ -199,21 +208,21 @@ const escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const atStart = (w: string) =>
w.endsWith('$') ? `${escapeRe(w.slice(0, -1))}(?![\\p{L}\\p{N}])` : escapeRe(w);
-/** Two patterns per topic: Latin and Cyrillic keywords at a word's start and Arabic ones anywhere,
- * on `normalise`d text; Vietnamese ones as whole words, on `normaliseVi`d text. */
+/** Two patterns per topic: Latin and Cyrillic keywords at a word's start and Arabic or Chinese
+ * ones anywhere, on `normalise`d text; Vietnamese ones as whole words, on `normaliseVi`d text. */
const PATTERNS: readonly [Topic, RegExp, RegExp][] = Object.values(TOPICS).map((topic) => {
const list = (langs: Lang[], fold: (s: string) => string, source = escapeRe) =>
langs.flatMap((l) => topic.words[l].split('|')).map((w) => source(fold(w)));
- const re = `(? {
diff --git a/apps/server/src/assistant/words.test.ts b/apps/server/src/assistant/words.test.ts
index f3b8ecff..0f40f7c4 100644
--- a/apps/server/src/assistant/words.test.ts
+++ b/apps/server/src/assistant/words.test.ts
@@ -3,13 +3,14 @@ import { noAnswer, viewerRefusal, wordsLocale } from './words.js';
// The assistant's fixed sentences: every interface language has its own.
-const ALL = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'] as const;
+const ALL = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const;
describe('wordsLocale()', () => {
it.each([
['es-MX', 'es'],
['uk-UA', 'uk'],
['vi', 'vi'],
+ ['zh-CN', 'zh'],
['fr-CA', 'fr'],
['ar', 'ar'],
['pt-BR', 'en'],
diff --git a/apps/server/src/assistant/words.ts b/apps/server/src/assistant/words.ts
index c8d47b80..b96b54cf 100644
--- a/apps/server/src/assistant/words.ts
+++ b/apps/server/src/assistant/words.ts
@@ -4,13 +4,13 @@
// isolated with FSI…PDI so it reads correctly inside a right-to-left sentence (lib/bidi.ts's rule
// on the web).
-export type WordsLocale = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+export type WordsLocale = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
const FSI = '';
const PDI = '';
const iso = (s: string) => `${FSI}${s}${PDI}`;
-const LOCALES: readonly WordsLocale[] = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'];
+const LOCALES: readonly WordsLocale[] = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'];
export function wordsLocale(locale: string): WordsLocale {
const base = locale.slice(0, 2).toLowerCase();
@@ -29,6 +29,7 @@ const VIEWER: Record string> = {
uk: (l) =>
`Спостерігачі не можуть вносити тут зміни. Запитайте адміністратора локації «${iso(l)}».`,
vi: (l) => `Người xem không thể thay đổi ở đây. Hãy nhờ một quản trị viên của ${iso(l)}.`,
+ zh: (l) => `访客无法在此进行更改。请联系「${iso(l)}」的管理员。`,
};
const NO_CHANGES: Record = {
@@ -40,6 +41,7 @@ const NO_CHANGES: Record = {
it: 'Non puoi fare modifiche qui.',
uk: 'Ви не можете вносити тут зміни.',
vi: 'Bạn không thể thay đổi ở đây.',
+ zh: '你无法在此进行更改。',
};
const NO_ANSWER: Record = {
@@ -51,6 +53,7 @@ const NO_ANSWER: Record = {
it: 'Non sono riuscito a completare la risposta. Chiedi di nuovo, magari in modo più preciso.',
uk: 'Мені не вдалося сформувати повну відповідь. Запитайте ще раз, можливо, конкретніше.',
vi: 'Tôi không thể hoàn thành câu trả lời đó. Hãy hỏi lại, có thể cụ thể hơn.',
+ zh: '我未能完成该回答。请换个更具体的问题再试一次。',
};
/** A viewer asked for a change, and the model tried one anyway. */
diff --git a/apps/server/src/exports/exports.test.ts b/apps/server/src/exports/exports.test.ts
index dc9fd998..99edae27 100644
--- a/apps/server/src/exports/exports.test.ts
+++ b/apps/server/src/exports/exports.test.ts
@@ -673,6 +673,17 @@ describe('the readable copy', () => {
expect(index).toContain('Copia legible');
});
+ it('takes a Simplified Chinese reader’s export, and writes its readable copy in Chinese (#532)', async () => {
+ const { id, outcome } = await exported(ibrahim, {
+ scope: { locationId: home.id },
+ options: { locale: 'zh', pdf: false, history: false },
+ });
+ expect(outcome.status, JSON.stringify(outcome)).toBe('done');
+ const index = text(await zipOf(id), 'readable/index.html');
+ expect(index).toContain('');
+ expect(index).toContain('可读副本');
+ });
+
it('holds more than the report cap, says why there is no PDF, and lists every thing', async () => {
const big = await createLocation(t, db, ibrahim, 'essentials', 'Warehouse');
await own(
diff --git a/apps/server/src/exports/service.ts b/apps/server/src/exports/service.ts
index b054c7f3..793e4761 100644
--- a/apps/server/src/exports/service.ts
+++ b/apps/server/src/exports/service.ts
@@ -47,8 +47,8 @@ export const ExportOptionsBody = z
aiCalls: z.boolean(),
readable: z.boolean(),
pdf: z.boolean(),
- // The web's languages; the readable copy is English or Arabic (readable/labels.ts).
- locale: z.enum(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi']),
+ // The web's languages; the readable copy follows them (readable/labels.ts).
+ locale: z.enum(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh']),
digits: z.enum(['western', 'eastern']),
})
.partial()
@@ -261,7 +261,7 @@ export async function createExport(
const { rows: profile } = await client.query<{ locale: string; digits: 'western' | 'eastern' }>(
'SELECT locale, digits FROM public.user_profiles WHERE user_id = kept.current_user_id()',
);
- const locale = (['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'] as const).find(
+ const locale = (['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const).find(
(l) => l === (profile[0]?.locale ?? '').slice(0, 2),
);
const options: ExportOptions = optionsOf({
diff --git a/apps/server/src/extraction/checks.test.ts b/apps/server/src/extraction/checks.test.ts
index 36486a89..2d527b78 100644
--- a/apps/server/src/extraction/checks.test.ts
+++ b/apps/server/src/extraction/checks.test.ts
@@ -113,6 +113,10 @@ describe("an alias in its language's script", () => {
['1234', 'en', false], // digits alone are no script
['дрель', 'ru', true],
['drill', 'ru', false],
+ ['电钻', 'zh', true],
+ ['LED 显示器', 'zh', true],
+ ['drill', 'zh', false],
+ ['iPhone 手机', 'zh', false],
['anything', 'xx', true], // a language the table doesn't know isn't checked
])('%s in %s: %s', (alias, lang, want) => {
expect(inLanguageScript(alias, lang)).toBe(want);
@@ -223,6 +227,8 @@ describe('placeholders and VIN formats seen in real runs', () => {
'KHONG BAO HANH',
'Без гарантії',
'Không bảo hành',
+ '无保修',
+ '不含保修。',
]) {
expect(terms(text).dropped, text).toEqual([
{ path: 'warranty_terms_printed', reason: 'not_terms' },
@@ -241,6 +247,8 @@ describe('placeholders and VIN formats seen in real runs', () => {
'Garantía de 2 años',
'Гарантія 2 роки',
'Bảo hành 2 năm',
+ '整机保修 2 年',
+ '全国联保一年',
]) {
expect(terms(text).fields.warrantyTermsPrinted?.value, text).toBe(text);
}
diff --git a/apps/server/src/extraction/checks.ts b/apps/server/src/extraction/checks.ts
index 6ab02800..30bc7396 100644
--- a/apps/server/src/extraction/checks.ts
+++ b/apps/server/src/extraction/checks.ts
@@ -175,7 +175,7 @@ const cap = (s: string, max: number) => s.trim().slice(0, max).trim();
/** What a model writes instead of leaving a field out (a real run, 2026-09-29: "N/A" at 0.95). */
const PLACEHOLDER =
- /^(?:n\/?a|none|null|nil|unknown|not (?:printed|shown|visible|available|applicable)|no warranty(?: terms)?|-+|—|غير متوفر|لا يوجد)$/i;
+ /^(?:n\/?a|none|null|nil|unknown|not (?:printed|shown|visible|available|applicable)|no warranty(?: terms)?|-+|—|غير متوفر|لا يوجد|无|未知|未标明)$/i;
/**
* Warranty terms (D55) must be about a warranty: the evaluation run (Groq, 2026-09-29) kept
@@ -184,9 +184,10 @@ const PLACEHOLDER =
* word in one of Kept's languages; "no warranty" in any of them, and text that talks about
* the model or its instructions, are not terms.
*/
-const WARRANTY_WORD = /warrant|guarant|ضمان|garanti|gewahrleist|garanzi|гаранті|bao hanh/;
+const WARRANTY_WORD =
+ /warrant|guarant|ضمان|garanti|gewahrleist|garanzi|гаранті|bao hanh|保修|质保|联保|三包/;
const WARRANTY_NONE =
- /^(?:none(?: printed)?|no (?:warranty|guarantee)(?: terms)?(?: printed)?|without (?:a )?(?:warranty|guarantee)|بدون ضمان|لا يوجد ضمان|sans garantie|ohne (?:garantie|gewahrleistung)|senza garanzia|sin garantia|no hay garantia|без гарантіі|немає гарантіі|khong (?:co )?bao hanh)[.!]?$/;
+ /^(?:none(?: printed)?|no (?:warranty|guarantee)(?: terms)?(?: printed)?|without (?:a )?(?:warranty|guarantee)|بدون ضمان|لا يوجد ضمان|sans garantie|ohne (?:garantie|gewahrleistung)|senza garanzia|sin garantia|no hay garantia|без гарантіі|немає гарантіі|khong (?:co )?bao hanh|无保修|没有保修|无质保|不含保修|不提供保修)[.。!!]?$/;
const PROMPT_ECHO = /\b(?:the model|instructions?|this field|leave it out|json)\b/i;
/** Lower case with the marks off, so terms read the same in capitals, typed without accents, or in
@@ -290,14 +291,16 @@ const SCRIPT_OF: Readonly> = Object.freeze({
bg: 'Cyrillic',
el: 'Greek',
he: 'Hebrew',
+ zh: 'Han',
});
-type Script = 'Latin' | 'Arabic' | 'Cyrillic' | 'Greek' | 'Hebrew';
+type Script = 'Latin' | 'Arabic' | 'Cyrillic' | 'Greek' | 'Hebrew' | 'Han';
const IN_SCRIPT: Readonly> = {
Latin: /\p{Script=Latin}/u,
Arabic: /\p{Script=Arabic}/u,
Cyrillic: /\p{Script=Cyrillic}/u,
Greek: /\p{Script=Greek}/u,
Hebrew: /\p{Script=Hebrew}/u,
+ Han: /\p{Script=Han}/u,
};
const LETTER = /\p{L}/u;
/** Letters no script owns: the Arabic tatweel, the Japanese long mark… */
diff --git a/apps/server/src/extraction/prompts/common.test.ts b/apps/server/src/extraction/prompts/common.test.ts
index d94fdf45..ac0ebcb7 100644
--- a/apps/server/src/extraction/prompts/common.test.ts
+++ b/apps/server/src/extraction/prompts/common.test.ts
@@ -3,8 +3,8 @@ import { languageList } from './common.js';
describe('languageList()', () => {
it('names every language Kept ships, and passes others as their code', () => {
- expect(languageList(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'xx'])).toBe(
- 'ar (Arabic), de (German), en (English), es (Spanish), fr (French), it (Italian), uk (Ukrainian), vi (Vietnamese), xx (xx)',
+ expect(languageList(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh', 'xx'])).toBe(
+ 'ar (Arabic), de (German), en (English), es (Spanish), fr (French), it (Italian), uk (Ukrainian), vi (Vietnamese), zh (Simplified Chinese), xx (xx)',
);
});
});
diff --git a/apps/server/src/extraction/prompts/common.ts b/apps/server/src/extraction/prompts/common.ts
index 2ac6331e..72fb0682 100644
--- a/apps/server/src/extraction/prompts/common.ts
+++ b/apps/server/src/extraction/prompts/common.ts
@@ -51,6 +51,7 @@ const LANGUAGE_NAMES: Readonly> = Object.freeze({
it: 'Italian',
uk: 'Ukrainian',
vi: 'Vietnamese',
+ zh: 'Simplified Chinese',
});
export function languageList(codes: readonly string[]): string {
diff --git a/apps/server/src/imports/dry-run.ts b/apps/server/src/imports/dry-run.ts
index fba7a694..d320f43e 100644
--- a/apps/server/src/imports/dry-run.ts
+++ b/apps/server/src/imports/dry-run.ts
@@ -291,7 +291,7 @@ export async function loadTypes(
AND NOT t.is_field_group AND t.archived_at IS NULL`,
[accountId],
);
- const locales: BuiltinNameLocale[] = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'];
+ const locales: BuiltinNameLocale[] = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'];
const namesOf = (key: string) =>
locales.map((l) => builtinTypeName(key, l)).filter((n): n is string => !!n);
// Built-ins first, so the account's own (and its customised copies) win.
diff --git a/apps/server/src/imports/imports.test.ts b/apps/server/src/imports/imports.test.ts
index b8b830ec..6a1cef77 100644
--- a/apps/server/src/imports/imports.test.ts
+++ b/apps/server/src/imports/imports.test.ts
@@ -527,6 +527,19 @@ describe('POST /api/v1/imports/:id/dry-run', () => {
);
expect(drill?.builtin_key).toBe('power_tool');
});
+
+ it('finds a built-in type by its Simplified Chinese name', async () => {
+ const workshop = await createLocation(t, db, ann, 'household', 'Workshop');
+ const { run } = await importRows(ann, workshop, [row({ Name: '电钻', Type: '电动工具' })]);
+ expect(run.status).toBe('done');
+ const [drill] = await own<{ builtin_key: string | null }>(
+ db,
+ `SELECT ty.builtin_key FROM public.things t JOIN public.types ty ON ty.id = t.type_id
+ WHERE t.location_id = $1`,
+ [workshop.id],
+ );
+ expect(drill?.builtin_key).toBe('power_tool');
+ });
});
describe('a purchase with a date and no price', () => {
diff --git a/apps/server/src/incidents/download.ts b/apps/server/src/incidents/download.ts
index 7a9def58..c79e9990 100644
--- a/apps/server/src/incidents/download.ts
+++ b/apps/server/src/incidents/download.ts
@@ -14,7 +14,7 @@ import { tokenHash } from './claim-pack.js';
// language: a link that never existed says the same, so a guess learns nothing. The token is
// redacted from the request log (http/logger.ts), and only its sha256 is ever stored.
-const LANGS = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'] as const;
+const LANGS = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const;
type Lang = (typeof LANGS)[number];
const EXPIRED: Record = {
@@ -50,6 +50,10 @@ const EXPIRED: Record = {
title: 'Liên kết này đã hết hạn',
body: 'Hãy xin liên kết mới từ người đã chia sẻ nó.',
},
+ zh: {
+ title: '此链接已过期',
+ body: '请向分享此链接的人索取新链接。',
+ },
};
/** The first language of Accept-Language that the page speaks, by q order; English otherwise. */
diff --git a/apps/server/src/incidents/helpers.test.ts b/apps/server/src/incidents/helpers.test.ts
index 29595b6d..5afb3fb6 100644
--- a/apps/server/src/incidents/helpers.test.ts
+++ b/apps/server/src/incidents/helpers.test.ts
@@ -17,6 +17,7 @@ describe('langOf() (the expired page)', () => {
['es-MX,en;q=0.5', 'es'],
['uk-UA', 'uk'],
['vi', 'vi'],
+ ['zh-CN,zh;q=0.9', 'zh'],
['xx,yy', 'en'],
])('%s → %s', (header, lang) => {
expect(langOf(header)).toBe(lang);
@@ -29,11 +30,13 @@ describe('langOf() (the expired page)', () => {
expect(expiredPage('en')).toContain('This link has expired
');
});
- it('speaks Spanish, Ukrainian and Vietnamese', () => {
+ it('speaks Spanish, Ukrainian, Vietnamese and Simplified Chinese', () => {
expect(expiredPage('es')).toContain('Este enlace ha expirado
');
expect(expiredPage('es')).toContain('');
expect(expiredPage('uk')).toContain('Термін дії цього посилання закінчився
');
expect(expiredPage('vi')).toContain('Liên kết này đã hết hạn
');
+ expect(expiredPage('zh')).toContain('此链接已过期
');
+ expect(expiredPage('zh')).toContain('');
});
});
diff --git a/apps/server/src/mail/mail.test.ts b/apps/server/src/mail/mail.test.ts
index 9911c40f..dac748cc 100644
--- a/apps/server/src/mail/mail.test.ts
+++ b/apps/server/src/mail/mail.test.ts
@@ -331,6 +331,7 @@ describe('the message table', () => {
expect(mailLocale('es-MX')).toBe('es');
expect(mailLocale('uk-UA')).toBe('uk');
expect(mailLocale('vi_VN')).toBe('vi');
+ expect(mailLocale('zh-CN')).toBe('zh');
expect(mailLocale('pt')).toBe('en');
expect(mailLocale('')).toBe('en');
expect(mailLocale(null)).toBe('en');
@@ -384,7 +385,7 @@ describe('the message table', () => {
});
it('writes every language beyond English and Arabic as its own text, never English left in', () => {
- for (const locale of ['de', 'es', 'fr', 'it', 'uk', 'vi'] as const) {
+ for (const locale of ['de', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const) {
for (const mail of EVERY_MAIL) {
const en = messageFor(mail, 'en', ctx);
const m = messageFor(mail, locale, ctx);
@@ -573,6 +574,7 @@ describe('counts in a sentence', () => {
expect(when('es')).toContain('6 de noviembre de 2026');
expect(when('uk')).toContain('6 листопада 2026');
expect(when('vi')).toContain('6 tháng 11, 2026');
+ expect(when('zh')).toContain('2026年11月6日');
});
});
@@ -675,6 +677,7 @@ describe('renderMail', () => {
['it', 'dir="ltr"'],
['uk', 'dir="ltr"'],
['vi', 'dir="ltr"'],
+ ['zh', 'dir="ltr"'],
];
for (const [locale, dir] of cases) {
const mail = EVERY_MAIL[0] as MailBody & { url: string };
diff --git a/apps/server/src/mail/messages-notify.ts b/apps/server/src/mail/messages-notify.ts
index 01ba054e..9ff2cd91 100644
--- a/apps/server/src/mail/messages-notify.ts
+++ b/apps/server/src/mail/messages-notify.ts
@@ -296,6 +296,37 @@ const WORDS: Record = {
footnote: 'Các kênh khác của bạn không bị ảnh hưởng.',
},
},
+ zh: {
+ where: '位置',
+ open: '在 Kept 中打开',
+ openKept: '打开 Kept',
+ digestSubject: (count, day) => `Kept:${day} 共有 ${count}`,
+ digestIntro: (day) => `截至 ${day} 即将到期与待处理的事项:`,
+ reminderFootnote: (url) =>
+ `你收到此邮件是因为你已启用此类提醒。可在「设置 → 我的 → 通知」中调整接收项:${url}`,
+ digestFootnote: (url) =>
+ `此每日摘要会在你设定的时间每天发送一次。可在「设置 → 我的 → 通知」中更改:${url}`,
+ role: { admin: '管理员', member: '成员', viewer: '访客' },
+ ended: {
+ subject: (member, location) => `${member} 对「${location}」的访问权限已到期`,
+ body: (member, location, role, day) =>
+ `${member} 作为${role}对「${location}」的访问权限已于设定的截止日期(${day})结束。`,
+ footnote: '作为地点所有者你会收到此通知。如需重新授权,请在地点设置中再次发送邀请。',
+ },
+ test: {
+ subject: 'Kept:测试通知',
+ body: '这是你在「设置 → 我的 → 通知」中发送的测试邮件。你选择通过邮件接收的提醒将发送至此邮箱。',
+ footnote: '没有更改其他任何设置。',
+ },
+ failing: {
+ subject: 'Kept:你的 Webhook 无响应',
+ body: (name) =>
+ `Kept 在过去约一天内尝试向你的 Webhook ${name} 投递提醒,但始终未收到响应,目前提醒无法送达该地址。`,
+ next: '请检查地址是否正确以及接收端是否正常运行,然后在「设置 → 我的 → 通知」中发送测试通知。',
+ action: '打开通知设置',
+ footnote: '你的其他通知渠道不受影响。',
+ },
+ },
};
/** The headline and the "where" line of one reminder, in `locale`. */
@@ -385,6 +416,15 @@ const SUMMARY: Record = {
footnote:
'Bạn nhận được thông báo này mỗi tháng một lần về AI do tài khoản hoặc khóa riêng của bạn trả tiền. Tắt nó trong Cài đặt → Tôi → Thông báo.',
},
+ zh: {
+ subject: (month) => `Kept:${month} AI 用量月报`,
+ line: (month, calls, tokens, cost) =>
+ `${month} AI 用量:${calls} 次调用,${tokens} token${cost ? `,约 ${cost}` : ''}。`,
+ unknown: (n) => `另有 ${n} 次调用未配置单价,因此未计入费用。`,
+ action: '查看 AI 用量',
+ footnote:
+ '针对由你的账户或自有密钥计费的 AI 调用,每月发送一次此摘要。可在「设置 → 我的 → 通知」中关闭。',
+ },
};
/** "September 2026" in `tag`, from YYYY-MM. */
@@ -481,4 +521,5 @@ export const NOTIFY_MESSAGES: Record = {
it: table('it'),
uk: table('uk'),
vi: table('vi'),
+ zh: table('zh'),
};
diff --git a/apps/server/src/mail/messages-transparency.ts b/apps/server/src/mail/messages-transparency.ts
index 20ae93bb..8b2c2c64 100644
--- a/apps/server/src/mail/messages-transparency.ts
+++ b/apps/server/src/mail/messages-transparency.ts
@@ -269,6 +269,34 @@ const WORDS: Record = {
},
providers: { ...NAMES, openai_compatible: 'máy chủ tương thích với OpenAI' },
},
+ zh: {
+ oidcOn: {
+ subject: (name) => `Kept 上的 ${name} 登录配置已变更`,
+ body: (name) =>
+ `运行此 Kept 的管理员更改了通过 ${name} 登录的配置。你的密码、通行密钥及邮件登录链接仍可照常使用。`,
+ },
+ oidcOff: {
+ subject: 'Kept 已关闭外部账号登录',
+ body: '运行此 Kept 的管理员已关闭外部账号登录。请使用密码、通行密钥或邮件登录链接进行登录。',
+ },
+ oidcFootnote:
+ '每当登录方式发生变更时,所有在此拥有账户的成员都会收到通知。如果出乎你的意料,请向运行此 Kept 的管理员确认。',
+ smtp: {
+ subject: (sender) => `Kept 现通过 ${sender} 发送邮件`,
+ body: (sender) =>
+ `运行此 Kept 的管理员更改了发信配置。正如本封邮件一样,今后系统邮件将由 ${sender} 发出。`,
+ footnote:
+ '每当发信地址发生变更时,所有在此拥有账户的成员都会收到通知。如果收到自称来自 Kept 但发件人不同的邮件,请勿点击其中的链接。',
+ },
+ ai: {
+ subject: (provider) => `Kept 的默认 AI 服务商现已改为 ${provider}`,
+ body: (provider) =>
+ `运行此 Kept 的管理员已将默认 AI 服务商更改为 ${provider}。凡使用此服务器默认 AI 的地点,你发送给 AI 的内容(照片、收据和提问)现将发往 ${provider}。`,
+ action: '打开 AI 设置',
+ footnote: 'AI 设置中列出了你每个地点所使用的服务商,地点所有者也可单独改选其他服务商。',
+ },
+ providers: { ...NAMES, openai_compatible: 'OpenAI 兼容服务端' },
+ },
};
function table(locale: MailLocale): TransparencyTable {
@@ -308,4 +336,5 @@ export const TRANSPARENCY_MESSAGES: Record = {
it: table('it'),
uk: table('uk'),
vi: table('vi'),
+ zh: table('zh'),
};
diff --git a/apps/server/src/mail/messages-zh.ts b/apps/server/src/mail/messages-zh.ts
new file mode 100644
index 00000000..823e8337
--- /dev/null
+++ b/apps/server/src/mail/messages-zh.ts
@@ -0,0 +1,486 @@
+// Simplified Chinese mail. Same shape as the English table in messages.ts; keep them in step.
+import type { SecurityEvent } from '../auth/security.js';
+import type { AdminAction, AiCapFacts } from './mailer.js';
+import {
+ aiPage,
+ type Chrome,
+ type CoreTable,
+ capFactsOf,
+ day,
+ deviceName,
+ diskFacts,
+ type Message,
+ type MessageContext,
+ mailDay,
+ mailTime,
+ num,
+ page,
+ tokens,
+} from './message-kit.js';
+
+const ZH_ROLE = { admin: '管理员', member: '成员', viewer: '访客' } as const;
+
+const ZH_NOT_YOU = '如果这不是你本人操作,请立即前往登录页重置密码。';
+
+const ZH_SECURITY: Record Message> = {
+ 'passkey-added': () => ({
+ subject: '你的 Kept 账户已添加通行密钥',
+ paragraphs: ['你的 Kept 账户已添加一个新的通行密钥,其他所有设备均已退出登录。'],
+ footnote: '如果这不是你本人操作,请立即重置密码,并在「设置 → 登录与安全」中移除该通行密钥。',
+ }),
+ 'two-factor-disabled': () => ({
+ subject: '两步验证已关闭',
+ paragraphs: ['你的 Kept 账户已关闭两步验证,其他所有设备均已退出登录。'],
+ footnote: '如果这不是你本人操作,请立即重置密码并重新开启两步验证。',
+ }),
+ 'passkey-removed': () => ({
+ subject: '你的 Kept 账户已移除一个通行密钥',
+ paragraphs: [
+ '你的 Kept 账户已移除一个通行密钥,其他所有设备均已退出登录。该通行密钥已无法用于登录。',
+ ],
+ footnote: ZH_NOT_YOU,
+ }),
+ 'two-factor-enabled': () => ({
+ subject: '两步验证已开启',
+ paragraphs: [
+ '你的 Kept 账户已开启两步验证,其他所有设备均已退出登录。今后登录时需要输入身份验证器应用生成的验证码。',
+ ],
+ footnote: '如果这不是你本人操作,请立即重置密码,并检查「设置 → 登录与安全」。',
+ }),
+ 'two-factor-replaced': () => ({
+ subject: '两步验证已重新配置',
+ paragraphs: [
+ '你的 Kept 账户已使用新的身份验证器应用重新配置两步验证,其他所有设备均已退出登录。旧验证器验证码及旧备用验证码均已失效。',
+ ],
+ footnote: '如果这不是你本人操作,请立即重置密码,并检查「设置 → 登录与安全」。',
+ }),
+ 'backup-codes-new': () => ({
+ subject: '你的 Kept 账户已生成新的备用验证码',
+ paragraphs: [
+ '你的 Kept 账户已生成新的两步验证备用验证码,其他所有设备均已退出登录。旧备用验证码已失效。',
+ ],
+ footnote: ZH_NOT_YOU,
+ }),
+ 'sign-in-unlinked': () => ({
+ subject: '你的 Kept 账户已解绑一种登录方式',
+ paragraphs: [
+ '一种外部登录方式(如 Google)已从你的 Kept 账户解绑,其他所有设备均已退出登录。你已无法再通过该方式登录。',
+ ],
+ footnote: ZH_NOT_YOU,
+ }),
+ 'password-changed': () => ({
+ subject: '你的 Kept 密码已更改',
+ paragraphs: ['你的 Kept 账户密码已更改,其他所有设备均已退出登录。'],
+ footnote: ZH_NOT_YOU,
+ }),
+ 'unverified-account-reset': () => ({
+ subject: '你的邮箱地址已验证',
+ paragraphs: [
+ '你的 Kept 密码已通过此邮箱完成重置,确认该账户邮箱归你本人所有。',
+ '由于该邮箱此前未经验证,为防止他人曾抢先注册,此前添加的所有通行密钥、两步验证配置及已登录设备均已清除。',
+ ],
+ footnote:
+ '请使用新密码登录,并在需要时重新开启两步验证。如果刚才重置密码的不是你本人,请立即再次重置。',
+ }),
+ 'unverified-account-link': () => ({
+ subject: '你的邮箱地址已验证',
+ paragraphs: [
+ '你已通过发送至此邮箱的链接登录 Kept,确认该账户邮箱归你本人所有。',
+ '由于该邮箱此前未经验证,为防止他人曾抢先设置账户,原有的密码、通行密钥、两步验证配置及其他已登录设备均已清除。',
+ ],
+ footnote: '请在账户设置中设置新密码,并在需要时重新开启两步验证。',
+ }),
+};
+
+const ZH_ADMIN: Record Message> = {
+ disabled: () => ({
+ subject: '你的 Kept 账户已被停用',
+ paragraphs: ['此 Kept 实例的管理员已停用你的账户。在重新启用之前,你将无法登录。'],
+ }),
+ enabled: () => ({
+ subject: '你的 Kept 账户已重新启用',
+ paragraphs: ['管理员已重新启用你的账户,你可以照常登录。'],
+ }),
+ 'two-factor-reset': () => ({
+ subject: '你账户的两步验证已被重置',
+ paragraphs: [
+ '管理员已移除你账户上的两步验证并退出了所有设备的登录(通常是因为验证器设备遗失)。',
+ '请在账户设置中重新配置两步验证。',
+ ],
+ }),
+ 'signed-out-everywhere': () => ({
+ subject: '你的 Kept 账户已在所有设备上退出登录',
+ paragraphs: ['管理员已将你的账户从所有设备退出登录。请重新登录以继续使用。'],
+ }),
+ 'instance-admin-granted': () => ({
+ subject: '你已成为此 Kept 的实例管理员',
+ paragraphs: ['你已被授予实例管理员权限,可以管理此 Kept 的用户与系统设置。'],
+ }),
+ 'instance-admin-revoked': () => ({
+ subject: '你已不再是此 Kept 的实例管理员',
+ paragraphs: ['你的实例管理员权限已被移除。你名下的地点及其中所有物品不受影响。'],
+ }),
+ 'password-reset-issued': () => ({
+ subject: '你的账户已获发一次性密码重置码',
+ paragraphs: [
+ '运行此 Kept 的管理员已为你的账户生成一次性密码重置码,并退出了所有设备的登录。',
+ '管理员会将重置码交给你,用于设置新密码。',
+ ],
+ }),
+ 'location-ownership-received': (name) => ({
+ subject: `你已成为「${name}」的所有者`,
+ paragraphs: [`运行此 Kept 的管理员已将「${name}」的所有权移交给你。`],
+ }),
+ 'location-ownership-moved': (name) => ({
+ subject: `「${name}」已更换所有者`,
+ paragraphs: [
+ `运行此 Kept 的管理员已将「${name}」移交给新的所有者。你仍保留该地点的管理员身份。`,
+ ],
+ }),
+ 'token-created': () => ({
+ subject: '你的账户已创建一个访问令牌',
+ paragraphs: [
+ '运行此 Kept 的管理员在服务器上为你的账户创建了个人访问令牌(供 Home Assistant 或 AI 助手等应用使用)。在所授权的地点内,该令牌拥有与你相同的操作权限。',
+ '如果这不是你本人申请的,请在「设置 → 连接」中将其撤销。',
+ ],
+ }),
+};
+
+// AI caps (D206): the cap in words, and how much of it is used.
+function zhCapOf(c: AiCapFacts): string {
+ switch (c.scope) {
+ case 'location':
+ return `「${c.target}」的 AI 限额`;
+ case 'member':
+ return c.target ? `${c.target} 的 AI 限额` : '成员的 AI 限额';
+ case 'account':
+ return '你账户的 AI 限额';
+ case 'user':
+ return '你的个人 AI 限额';
+ case 'instance':
+ return '此服务器的 AI 限额';
+ case 'instance_account':
+ return c.target ? `${c.target} 在此服务器 AI 密钥上的配额` : '此服务器 AI 密钥上的账户配额';
+ }
+}
+
+const zhUsed = (c: AiCapFacts) =>
+ c.unit === 'money'
+ ? `${c.currency} ${c.used} / ${c.currency} ${c.limit}`
+ : `${tokens('zh-CN', c.used)} / ${tokens('zh-CN', c.limit)} token`;
+
+function zhCap(level: 80 | 100, c: AiCapFacts, ctx: MessageContext, footnote: string): Message {
+ const cap = zhCapOf(c);
+ if (level === 80) {
+ return {
+ subject: `Kept:本月已使用 ${cap} 的 80%`,
+ paragraphs: [
+ `${cap}本月已使用 ${zhUsed(c)}。`,
+ '达到上限后,AI 功能将暂停至下月 1 日。在此期间采集的照片仍会照常保存,并在恢复后继续识别。',
+ ],
+ action: { label: '打开 AI 设置', url: aiPage(ctx, c.scope) },
+ footnote,
+ };
+ }
+ return {
+ subject: `Kept:AI 已暂停至 ${day(c.pausedUntil)}`,
+ paragraphs: [
+ `${cap}已达上限:本月已使用 ${zhUsed(c)}。`,
+ `AI 功能将暂停至 ${day(c.pausedUntil)}。在此期间采集的照片仍会照常保存,并在恢复后继续识别。如需提前恢复,请调高或移除该限额。`,
+ ],
+ action: { label: '立即恢复', url: aiPage(ctx, c.scope) },
+ footnote,
+ };
+}
+
+export const ZH: CoreTable = {
+ 'magic-link': (m) => ({
+ subject: '你的 Kept 登录链接',
+ paragraphs: ['点击此链接即可登录 Kept。链接仅可使用一次,有效期为 15 分钟。'],
+ action: { label: '登录', url: m.url },
+ footnote: '如果你未申请登录,请忽略此邮件。没有此链接,任何人都无法登录你的账户。',
+ }),
+ 'password-reset': (m) => ({
+ subject: '重置你的 Kept 密码',
+ paragraphs: [
+ '有人请求重置此 Kept 账户的密码。点击下方链接即可设置新密码。链接仅可使用一次,有效期为 1 小时。',
+ ],
+ action: { label: '设置新密码', url: m.url },
+ footnote: '如果这不是你本人操作,请忽略此邮件,你的原密码不会改变。',
+ }),
+ 'email-change-confirm': (m) => ({
+ subject: '确认你的新邮箱地址',
+ paragraphs: [
+ `已登录你 Kept 账户的用户请求将绑定邮箱更改为 ${m.newEmail}。如果是你本人操作,请在 1 小时内通过下方链接确认。`,
+ ],
+ action: { label: '确认更改', url: m.url },
+ footnote: '如果这不是你本人操作,请勿点击链接:你的账户仍保留在当前邮箱,建议尽快修改密码。',
+ }),
+ 'email-change-verify': (m) => ({
+ subject: '验证用于 Kept 的邮箱地址',
+ paragraphs: ['点击下方链接,完成将你的 Kept 账户迁移至此邮箱地址。'],
+ action: { label: '验证此邮箱', url: m.url },
+ footnote: '如果你未进行此操作,请忽略此邮件:在点击链接前不会发生任何更改。',
+ }),
+ 'email-changed': (m) => ({
+ subject: '你的 Kept 账户邮箱已更改',
+ paragraphs: [`你的 Kept 账户现已改用 ${m.newEmail}。当前邮箱将不再接收来自该账户的邮件。`],
+ footnote: '如果这不是你本人操作,请联系运行此 Kept 的管理员。',
+ }),
+ 'account-deletion': (m) => {
+ const when = mailDay('zh-CN', m.purgeAfter, m.timezone);
+ return {
+ subject: `你的 Kept 账户将于 ${when} 删除`,
+ paragraphs: [
+ `你已申请删除自己的 Kept 账户。该账户将于 ${when} 正式删除,届时你的「个人」地点及其中的全部物品也将一并清除。`,
+ '在此日期之前,登录账户可查看删除日期并随时选择保留账户。你在他人地点中添加的内容仍会保留在原处。',
+ ],
+ footnote: '如果这不是你本人操作,请立即登录并选择「保留我的账户」,同时修改密码。',
+ };
+ },
+ 'report-ready': (m) => {
+ const name = {
+ inventory: '物品清单报告',
+ insurance: '保险理赔报告',
+ vehicle_history: '车辆历史报告',
+ }[m.report];
+ return {
+ subject: m.place ? `${name}:${m.place}` : name,
+ paragraphs: [
+ m.attached
+ ? 'Kept 已生成你请求的报告,PDF 文件已随附于本邮件中。'
+ : 'Kept 已生成你请求的报告,但文件体积过大无法作为邮件附件发送。请返回 Kept 重新导出并下载。',
+ ],
+ footnote: '定时发送的报告列于「设置 → 我的 → 通知」中,你可随时前往停用。',
+ };
+ },
+ invite: (m) => ({
+ subject: m.inviterName
+ ? `${m.inviterName} 邀请你加入 Kept 上的「${m.locationName}」`
+ : `你受邀加入 Kept 上的「${m.locationName}」`,
+ paragraphs: [
+ m.inviterName
+ ? `${m.inviterName} 邀请你以${ZH_ROLE[m.role]}身份加入「${m.locationName}」。`
+ : `你受邀以${ZH_ROLE[m.role]}身份加入「${m.locationName}」。`,
+ 'Kept 用于记录你拥有的物品、存放位置以及即将到期的保修与待办事项。',
+ ],
+ action: { label: '接受邀请', url: m.url },
+ footnote: '如果你不认识此邀请,请忽略此邮件:在你接受之前不会发生任何操作。',
+ }),
+ 'sign-up-existing': (_m, ctx) => ({
+ subject: '有人尝试使用你的邮箱注册 Kept',
+ paragraphs: [
+ '有人尝试使用此邮箱地址创建 Kept 账户,但该邮箱已注册过账户,因此未创建新账户。',
+ '如果是你本人操作,请直接登录;如忘记密码,可在登录页重置密码。',
+ ],
+ action: { label: '前往登录', url: page(ctx, '/signin') },
+ footnote: '如果这不是你本人操作,无需进行任何处理。',
+ }),
+ 'security-notice': (m, ctx) => ZH_SECURITY[m.event](ctx),
+ 'backup-code-used': (m) => {
+ const when = mailTime('zh-CN', m.at, m.timeZone);
+ const device = deviceName(m, (browser, os) => `${os} 上的 ${browser}`);
+ return {
+ subject: '有人使用备用验证码登录了你的 Kept 账户',
+ paragraphs: [
+ device
+ ? `${when},有人通过 ${device} 使用备用验证码登录了你的 Kept 账户。`
+ : `${when},有人使用备用验证码登录了你的 Kept 账户。`,
+ m.left === 0
+ ? '这是你的最后一个备用验证码。请在「设置 → 登录与安全 → 生成新备用验证码」中重新生成。'
+ : `你还剩余 ${m.left} 个备用验证码。`,
+ '如果你是因为原身份验证器不可用而使用了备用验证码,请在「设置 → 登录与安全 → 重新配置」中绑定新应用,同时获取新的备用验证码。',
+ ],
+ footnote:
+ '如果这不是你本人操作,请立即在登录页重置密码;随后前往「设置 → 登录与安全 → 生成新备用验证码」(旧验证码将立即作废),并在「设置 → 会话与设备 → 退出所有其他设备」中踢出其余会话。',
+ };
+ },
+ 'admin-action': (m) => ({
+ ...ZH_ADMIN[m.action](m.locationName ?? ''),
+ footnote: '这是一封关于你账户状态变更的系统通知邮件。',
+ }),
+ 'owner-new-member': (m) => ({
+ subject: `${m.memberName} 已加入「${m.locationName}」`,
+ paragraphs: [
+ m.managed
+ ? `${m.memberName} 已作为托管账户添加至「${m.locationName}」,角色为${ZH_ROLE[m.role]}。`
+ : `${m.memberName} 现可以${ZH_ROLE[m.role]}身份访问「${m.locationName}」。`,
+ ],
+ footnote:
+ '作为地点所有者,每当有新成员加入时你都会收到此通知。你可在地点设置中调整权限或移除成员。',
+ }),
+ 'ai-cap': (m, ctx) =>
+ zhCap(
+ m.level,
+ m.cap,
+ ctx,
+ '你收到此邮件是因为该限额由你设置或适用于你的操作。每个限额周期每月最多发送一次。',
+ ),
+ 'admin-alert': (m, ctx) => {
+ const footnote =
+ '你收到此邮件是因为你是此 Kept 的实例管理员。问题持续期间每天最多发送一次提醒。';
+ if (m.alert === 'ai_instance_cap_warning' || m.alert === 'ai_instance_cap_reached') {
+ const c = capFactsOf(m.details);
+ if (c) return zhCap(m.alert === 'ai_instance_cap_warning' ? 80 : 100, c, ctx, footnote);
+ }
+ if (m.alert === 'ai_instance_key_rejected') {
+ return {
+ subject: 'Kept:实例 AI 密钥被拒绝',
+ paragraphs: [
+ `${String(m.details.provider ?? '服务商')} 拒绝了此服务器的 AI 密钥,使用该密钥计费的识别与问答任务目前处于排队等待状态。`,
+ '请在管理员 AI 设置中更换有效密钥,保存后排队中的任务将自动继续执行。',
+ ],
+ action: { label: '打开 AI 设置', url: page(ctx, '/admin/ai') },
+ footnote,
+ };
+ }
+ if (m.alert === 'failed_jobs_rising') {
+ return {
+ subject: 'Kept:后台任务出现失败',
+ paragraphs: [
+ `过去一小时内有 ${num(m.details.failedLastHour)} 个后台任务执行失败。`,
+ '可在失败任务列表中查看具体任务与失败原因,并选择重试或丢弃。',
+ ],
+ action: { label: '查看失败任务', url: page(ctx, '/admin/jobs') },
+ footnote,
+ };
+ }
+ if (m.alert === 'backup_failed') {
+ return {
+ subject: 'Kept:夜间自动备份失败',
+ paragraphs: [
+ `夜间备份未能完成:${String(m.details.error ?? '')}`,
+ m.details.lastOk
+ ? `最近一次成功备份完成于 ${day(m.details.lastOk)}。在下次备份成功前,此后新增的数据尚未进入备份库。`
+ : '目前尚无任何成功备份记录,此 Kept 中的数据尚未得到备份保护。',
+ ],
+ action: { label: '打开状态页', url: page(ctx, '/admin/status') },
+ footnote,
+ };
+ }
+ if (m.alert === 'backup_stale') {
+ return {
+ subject: 'Kept:已超过 36 小时未完成备份',
+ paragraphs: [
+ m.details.lastOkAt
+ ? `最近一次有效备份完成于 ${day(m.details.lastOkAt)}。Kept 默认每晚自动备份,说明夜间备份任务已停止正常运行。`
+ : '已配置备份存储,但迄今尚未完成过任何备份。',
+ '备份页面列出了每次运行记录与失败原因;如果后台 worker 进程未运行,请将其重启。',
+ ],
+ action: { label: '打开备份设置', url: page(ctx, '/admin/backups') },
+ footnote,
+ };
+ }
+ if (m.alert === 'disk_space_low') {
+ const d = diskFacts(m.details);
+ return {
+ subject: d.backup ? 'Kept:备份磁盘空间即将耗尽' : 'Kept:数据磁盘空间即将耗尽',
+ paragraphs: [
+ `磁盘已使用 ${d.percent}%,仅剩 ${d.gb} GB 可用空间。`,
+ d.backup
+ ? '磁盘写满后夜间备份将会失败。请清理空间、扩容磁盘,或在备份设置中减少保留份数。'
+ : '磁盘写满后 Kept 将无法保存新照片或文档,数据库也可能停止工作。请尽快清理空间或扩容磁盘。',
+ ],
+ action: { label: '打开状态页', url: page(ctx, '/admin/status') },
+ footnote,
+ };
+ }
+ if (m.alert === 'bucket_versioning_off') {
+ return {
+ subject: 'Kept:文件存储桶未开启版本控制',
+ paragraphs: [
+ 'Kept 将附件保存在 S3 存储桶中,夜间备份不会重复打包桶内原文件。当前存储桶未开启版本控制,一旦文件被误删或被持有密钥的人覆盖,将无法恢复。',
+ '请在对象存储服务商控制台中开启存储桶版本控制(Bucket Versioning);下次备份检测到开启后本提醒将自动解除。',
+ ],
+ action: { label: '打开状态页', url: page(ctx, '/admin/status') },
+ footnote,
+ };
+ }
+ if (m.alert === 'restore_drill_due') {
+ return {
+ subject: 'Kept:建议执行备份恢复演练',
+ paragraphs: [
+ m.details.lastDrillAt
+ ? `上次恢复演练执行于 ${day(m.details.lastDrillAt)},距今已超过 30 天。`
+ : '目前尚未执行过备份恢复演练。',
+ '恢复演练会将最新备份还原至临时数据库并校验所有数据表,确保备份真正可用。请参照恢复指南运行 `kept admin backup drill`。',
+ ],
+ action: { label: '打开备份设置', url: page(ctx, '/admin/backups') },
+ footnote,
+ };
+ }
+ if (m.alert === 'backup_verify_failed') {
+ return {
+ subject: 'Kept:每周备份校验发现异常',
+ paragraphs: [
+ `备份仓库的每周完整性校验失败:${String(m.details.error ?? '')}`,
+ '当前备份可能无法按原样恢复。请打开备份页面查看详情,并在修复后重新运行校验。',
+ ],
+ action: { label: '打开备份设置', url: page(ctx, '/admin/backups') },
+ footnote,
+ };
+ }
+ if (m.alert === 'backup_suspicious_size') {
+ return {
+ subject: 'Kept:最新备份体积异常偏小',
+ paragraphs: [
+ '最新一次备份比上一次有效备份小得多。Kept 已保留本次快照,同时暂停清理旧快照,以确保历史完好备份不被修剪。',
+ '如果近期确实主动删除了大量数据,则无需担心,后续备份会自动解除此警告;否则请在执行任何恢复操作前排查原因。',
+ ],
+ action: { label: '打开备份设置', url: page(ctx, '/admin/backups') },
+ footnote,
+ };
+ }
+ if (m.alert === 'webhook_failing') {
+ return {
+ subject: 'Kept:某地点的 Webhook 持续投递失败',
+ paragraphs: [
+ `此 Kept 中某个地点配置的 Webhook 自 ${day(m.details.since)} 起每次投递均告失败,已被标记为异常。`,
+ '新事件产生时 Kept 仍会继续尝试。该地点的所有者和管理员可在「地点设置 → Webhook」中查看并修复或删除它。',
+ ],
+ action: { label: '打开状态页', url: page(ctx, '/admin/status') },
+ footnote,
+ };
+ }
+ if (m.alert === 'reminders_not_scanned') {
+ return {
+ subject: 'Kept:到期提醒扫描已停止',
+ paragraphs: [
+ m.details.lastOkAt
+ ? `Kept 上次检查到期提醒是在 ${day(m.details.lastOkAt)}(已超过 2 小时)。在恢复扫描前不会发送任何新提醒。`
+ : 'Kept 尚未成功完成过到期提醒检查,因此目前无人会收到提醒。',
+ '后台 worker 每 15 分钟执行一次扫描。请查看失败任务列表排查停摆原因;若后台 worker 未运行,请将其重启。',
+ ],
+ action: { label: '查看失败任务', url: page(ctx, '/admin/jobs') },
+ footnote,
+ };
+ }
+ if (m.alert === 'llm_default_partition') {
+ return {
+ subject: 'Kept:AI 调用日志分区需要处理',
+ paragraphs: [
+ `共有 ${num(m.details.rows)} 条 AI 调用记录(${day(m.details.oldest)} 至 ${day(m.details.newest)})落入了默认分区而非月度分区。`,
+ '在这些记录迁入对应月度分区之前,Kept 无法创建该月分区,夜间维护任务将持续报错。请由运维此 Kept 的管理员在数据库层迁移处理。',
+ ],
+ action: { label: '打开状态页', url: page(ctx, '/admin/status') },
+ footnote,
+ };
+ }
+ return {
+ subject: 'Kept:审计日志分区需要处理',
+ paragraphs: [
+ `共有 ${num(m.details.rows)} 条审计事件(${day(m.details.oldest)} 至 ${day(m.details.newest)})落入了默认分区而非月度分区。`,
+ '在这些记录迁入对应月度分区之前,Kept 无法创建该月分区,夜间维护任务将持续报错。请由运维此 Kept 的管理员在数据库层迁移处理。',
+ ],
+ action: { label: '打开状态页', url: page(ctx, '/admin/status') },
+ footnote,
+ };
+ },
+};
+
+export const ZH_CHROME: Chrome = {
+ dir: 'ltr',
+ linkFallback: '如果按钮无法点击,请将以下地址复制到浏览器中打开:',
+ sentBy: (host) => `由位于 ${host} 的 Kept 发送。`,
+ about: (site) => `Kept,开源自托管家庭物品清单系统:${site}`,
+};
diff --git a/apps/server/src/mail/messages.ts b/apps/server/src/mail/messages.ts
index bfb9e0ab..182c86d6 100644
--- a/apps/server/src/mail/messages.ts
+++ b/apps/server/src/mail/messages.ts
@@ -26,6 +26,7 @@ import { NOTIFY_MESSAGES } from './messages-notify.js';
import { TRANSPARENCY_MESSAGES } from './messages-transparency.js';
import { UK, UK_CHROME } from './messages-uk.js';
import { VI, VI_CHROME } from './messages-vi.js';
+import { ZH, ZH_CHROME } from './messages-zh.js';
export type { Chrome, Message, MessageContext } from './message-kit.js';
@@ -35,7 +36,7 @@ export type { Chrome, Message, MessageContext } from './message-kit.js';
// error, so a new mail kind can't ship untranslated. The test checks every kind renders in each.
// English and Arabic live here; every other language in messages-.ts.
-export const MAIL_LOCALES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'] as const;
+export const MAIL_LOCALES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const;
export type MailLocale = (typeof MAIL_LOCALES)[number];
/** The mail language for a BCP 47 tag (`ar-EG` → `ar`, `fr-CA` → `fr`); English for anything else. */
@@ -1035,6 +1036,7 @@ export const MESSAGES: Record = {
it: { ...IT, ...NOTIFY_MESSAGES.it, ...TRANSPARENCY_MESSAGES.it },
uk: { ...UK, ...NOTIFY_MESSAGES.uk, ...TRANSPARENCY_MESSAGES.uk },
vi: { ...VI, ...NOTIFY_MESSAGES.vi, ...TRANSPARENCY_MESSAGES.vi },
+ zh: { ...ZH, ...NOTIFY_MESSAGES.zh, ...TRANSPARENCY_MESSAGES.zh },
};
export const CHROME: Record = {
@@ -1056,6 +1058,7 @@ export const CHROME: Record = {
it: IT_CHROME,
uk: UK_CHROME,
vi: VI_CHROME,
+ zh: ZH_CHROME,
};
/** What `mail` says in `locale`. */
diff --git a/apps/server/src/notify/push.ts b/apps/server/src/notify/push.ts
index d957318c..7738dd71 100644
--- a/apps/server/src/notify/push.ts
+++ b/apps/server/src/notify/push.ts
@@ -248,6 +248,7 @@ const TEST_PUSH: Record = {
it: { title: 'Kept', body: 'Le notifiche arrivano su questo dispositivo.' },
uk: { title: 'Kept', body: 'Сповіщення надходять на цей пристрій.' },
vi: { title: 'Kept', body: 'Thông báo đến được thiết bị này.' },
+ zh: { title: 'Kept', body: '通知已可送达此设备。' },
};
/** The test send's payload (Settings → Me → Notifications → Test). */
diff --git a/apps/server/src/notify/words.test.ts b/apps/server/src/notify/words.test.ts
index 02afc0a8..9c6085dc 100644
--- a/apps/server/src/notify/words.test.ts
+++ b/apps/server/src/notify/words.test.ts
@@ -27,6 +27,7 @@ const NAMES: Record): ReminderFacts {
@@ -162,6 +163,8 @@ describe('reminder wording', () => {
expect(REMINDER_COUNT.de(2)).toBe('2 Erinnerungen');
expect(REMINDER_COUNT.vi(1)).toBe('1 lời nhắc');
expect(REMINDER_COUNT.vi(5)).toBe('5 lời nhắc');
+ expect(REMINDER_COUNT.zh(1)).toBe('1 条提醒');
+ expect(REMINDER_COUNT.zh(5)).toBe('5 条提醒');
expect(REMINDER_COUNT.es(1)).toBe('1 recordatorio');
expect(REMINDER_COUNT.es(2)).toBe('2 recordatorios');
// Ukrainian: 1 and 21 take one form, 2 to 4 another that reads the same, 5 and 11 the third.
diff --git a/apps/server/src/notify/words.ts b/apps/server/src/notify/words.ts
index 58072e3d..410b3581 100644
--- a/apps/server/src/notify/words.ts
+++ b/apps/server/src/notify/words.ts
@@ -187,6 +187,14 @@ const ES_DOCS: Record = {
lease: 'El arrendamiento',
contract: 'El contrato',
};
+const ZH_DOCS: Record = {
+ registration: '登记证',
+ insurance: '保险单',
+ licence: '牌照许可',
+ inspection: '年检记录',
+ lease: '租赁合同',
+ contract: '合同',
+};
const EN = words(
'en',
@@ -573,6 +581,53 @@ const ES = words(
},
);
+const ZH = words(
+ 'zh-CN',
+ (f, day) => (f.sourceType === 'registration' ? `需在 ${day} 前` : `于 ${day}`),
+ (v) => `达到 ${v} 时`,
+ {
+ schedule: {
+ any: (n, w, f) => `「${n}」的${f.title ?? '保养计划'}${w}到期`,
+ overdue: (n, w, f) => `「${n}」的${f.title ?? '保养计划'}已${w}逾期`,
+ },
+ warranty: {
+ any: (n, w, f) => `「${n}」${provider(f, (p) => `(${p})`)}的保修${w}到期`,
+ },
+ registration: {
+ any: (n, w, f) => `「${n}」${provider(f, (p) => `(${p})`)}的保修${w}完成注册`,
+ },
+ document: {
+ any: (n, w, f) => `「${n}」的${docTitle(f, ZH_DOCS, '文档')}${w}到期`,
+ overdue: (n, w, f) => `「${n}」的${docTitle(f, ZH_DOCS, '文档')}已${w}过期`,
+ },
+ loan: { any: (n, w) => `「${n}」应${w}归还` },
+ thing_expiry: {
+ any: (n, w) => `「${n}」${w}到期`,
+ overdue: (n, w) => `「${n}」已${w}过期`,
+ },
+ stock: { any: (n, w) => `「${n}」库存${w}偏低` },
+ reading_stale: {
+ any: stale(
+ 'zh-CN',
+ { distance: '里程表', hours: '计时表', custom: '表计' },
+ (l) => `「${l}」`,
+ (m, n, day) => `「${n}」上的${m}上次记录读数是在 ${day}`,
+ (m, n, w) => `「${n}」上的${m}${w}需要更新读数`,
+ ),
+ },
+ },
+ {
+ schedule: (f) => f.title ?? '待办保养',
+ warranty: () => '保修到期',
+ registration: () => '注册保修',
+ document: (f) => docTitle(f, ZH_DOCS, '文档到期'),
+ loan: () => '待归还',
+ thing_expiry: () => '物品到期',
+ reading_stale: () => '需更新读数',
+ stock: () => '库存偏低',
+ },
+);
+
export const REMINDER_WORDS: Record = {
ar: AR,
de: DE,
@@ -582,6 +637,7 @@ export const REMINDER_WORDS: Record = {
it: IT,
uk: UK,
vi: VI,
+ zh: ZH,
};
/** The calendar event's title and a push notification's: "Boiler service, Kitchen". */
@@ -622,4 +678,5 @@ export const REMINDER_COUNT: Record string> = {
}
},
vi: (n) => `${n} lời nhắc`,
+ zh: (n) => `${n} 条提醒`,
};
diff --git a/apps/server/src/paperless/kinds.ts b/apps/server/src/paperless/kinds.ts
index 3fe6ede2..cef9aa22 100644
--- a/apps/server/src/paperless/kinds.ts
+++ b/apps/server/src/paperless/kinds.ts
@@ -23,6 +23,8 @@ const WORDS: readonly [PaperlessKind, readonly string[]][] = [
'гарантії',
'гарантійний',
'bảo hành',
+ '保修',
+ '质保',
],
],
[
@@ -45,6 +47,10 @@ const WORDS: readonly [PaperlessKind, readonly string[]][] = [
'посібник',
'посібники',
'hướng dẫn',
+ '说明书',
+ '使用手册',
+ '用户手册',
+ '操作指南',
],
],
[
@@ -61,6 +67,7 @@ const WORDS: readonly [PaperlessKind, readonly string[]][] = [
'рахунок',
'рахунки',
'hóa đơn',
+ '发票',
],
],
[
@@ -86,6 +93,8 @@ const WORDS: readonly [PaperlessKind, readonly string[]][] = [
'квитанції',
'biên lai',
'phiếu thu',
+ '收据',
+ '小票',
],
],
];
@@ -100,7 +109,12 @@ const wordsOf = (s: string) =>
.filter(Boolean)
.join(' ');
-const FOLDED = WORDS.map(([kind, words]) => [kind, words.map((w) => ` ${wordsOf(w)} `)] as const);
+const HAN = /\p{Script=Han}/u;
+
+const FOLDED = WORDS.map(
+ ([kind, words]) =>
+ [kind, words.map((w) => (HAN.test(w) ? wordsOf(w) : ` ${wordsOf(w)} `))] as const,
+);
/** Names that hold a kind's word and mean something else: a checklist, proof of address, a bank
* account. They're taken out before matching. */
diff --git a/apps/server/src/paperless/paperless.test.ts b/apps/server/src/paperless/paperless.test.ts
index d0eca4e8..66477477 100644
--- a/apps/server/src/paperless/paperless.test.ts
+++ b/apps/server/src/paperless/paperless.test.ts
@@ -339,6 +339,10 @@ describe('the Paperless client', () => {
expect(kindOf('Bảo hành máy khoan', [])).toBe('warranty_doc');
expect(kindOf('Sách hướng dẫn', [])).toBe('manual');
expect(kindOf('Biên lai', [])).toBe('receipt');
+ expect(kindOf('冰箱电子发票', [])).toBe('invoice');
+ expect(kindOf('电钻保修卡', [])).toBe('warranty_doc');
+ expect(kindOf('洗衣机说明书', [])).toBe('manual');
+ expect(kindOf('超市购物小票', [])).toBe('receipt');
});
it("doesn't take one syllable of a Vietnamese word for the word", () => {
diff --git a/apps/server/src/reports/languages.test.ts b/apps/server/src/reports/languages.test.ts
index c59a8911..a6d3d7ed 100644
--- a/apps/server/src/reports/languages.test.ts
+++ b/apps/server/src/reports/languages.test.ts
@@ -103,6 +103,7 @@ describe('the PDF words', () => {
!k.startsWith('vehicle.units.') && k !== 'vehicle.mpg()' && k !== 'vehicle.miPerKwh()',
),
vi: shared,
+ zh: shared,
};
for (const l of REPORT_LOCALES) {
const words = leaves(PDF_WORDS[l]);
@@ -152,11 +153,13 @@ describe('the PDF words', () => {
]);
expect([1, 2].map((n) => count('it', n))).toEqual(['1 oggetto', '2 oggetti']);
expect([1, 2].map((n) => count('vi', n))).toEqual(['1 đồ vật', '2 đồ vật']);
+ expect([1, 2].map((n) => count('zh', n))).toEqual(['1 件物品', '2 件物品']);
});
it('takes the language of a tag, and English for one Kept doesn’t speak', () => {
expect(reportLocaleOf('fr-CA')).toBe('fr');
expect(reportLocaleOf('uk_UA')).toBe('uk');
+ expect(reportLocaleOf('zh-CN')).toBe('zh');
expect(reportLocaleOf('AR-eg')).toBe('ar');
expect(reportLocaleOf('pt-BR')).toBe('en');
expect(reportLocaleOf(null)).toBe('en');
@@ -562,6 +565,11 @@ describe('the views', () => {
expect(fr.places.find((p) => p.pathText === 'Hall')?.count).toBe('2 objets');
expect(inventory('uk').places.find((p) => p.pathText === 'Hall')?.count).toBe('2 речі');
expect(inventory('uk').generatedLine).toMatch(/^Створено: Bruce, 26 вересня 2026/);
+ const zh = inventory('zh');
+ expect(zh.colon).toBe(':');
+ expect(zh.labels.title).toBe('物品清单报告');
+ expect(zh.filters).toContain('位置:Kitchen, Hall');
+ expect(zh.places.find((p) => p.pathText === 'Hall')?.count).toBe('2 件物品');
const ins = insurance('es');
expect(ins.labels.title).toBe('Reporte de seguro');
expect(ins.incident).toEqual({
diff --git a/apps/server/src/reports/locale.ts b/apps/server/src/reports/locale.ts
index 843c9289..4d6a072d 100644
--- a/apps/server/src/reports/locale.ts
+++ b/apps/server/src/reports/locale.ts
@@ -4,7 +4,7 @@ import type { Digits } from '@kept/shared';
// (mail/messages.ts). What each says lives in words/.ts; this file holds how each one
// writes what isn't a word: its Intl locale, digits, direction and punctuation.
-export const REPORT_LOCALES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'] as const;
+export const REPORT_LOCALES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const;
export type ReportLocale = (typeof REPORT_LOCALES)[number];
/** The report language for a BCP 47 tag (`ar-EG` → `ar`, `fr-CA` → `fr`); English for anything
@@ -17,9 +17,9 @@ export function reportLocaleOf(tag: string | null | undefined): ReportLocale {
}
/** The Intl locale dates and numbers are written in: Egyptian Arabic and British English as
- * before, every other language as itself. */
+ * before, Simplified Chinese as zh-CN, every other language as itself. */
export const intlLocaleOf = (locale: ReportLocale): string =>
- locale === 'ar' ? 'ar-EG' : locale === 'en' ? 'en-GB' : locale;
+ locale === 'ar' ? 'ar-EG' : locale === 'en' ? 'en-GB' : locale === 'zh' ? 'zh-CN' : locale;
/** Eastern digits only in Arabic, when the reader asked for them (D143). */
export const numberingOf = (locale: ReportLocale, digits: Digits): 'latn' | 'arab' =>
@@ -33,8 +33,10 @@ export const sepOf = (locale: ReportLocale): string => (locale === 'ar' ? '، '
/** Between a path's steps, pointing from the outer place to the inner one. */
export const pathSeparatorOf = (locale: ReportLocale): '›' | '‹' => (locale === 'ar' ? '‹' : '›');
-/** After a label ("Serial number: …"): French puts a no-break space before the colon. */
-export const colonOf = (locale: ReportLocale): string => (locale === 'fr' ? ' : ' : ': ');
+/** After a label ("Serial number: …"): French puts a no-break space before the colon, Chinese uses
+ * its fullwidth colon. */
+export const colonOf = (locale: ReportLocale): string =>
+ locale === 'fr' ? ' : ' : locale === 'zh' ? ':' : ': ';
/** The plural form `n` takes in `locale` (Arabic's six, Ukrainian's four, one in Vietnamese). */
export const pluralOf = (locale: ReportLocale, n: number): Intl.LDMLPluralRule =>
diff --git a/apps/server/src/reports/render/build-assets.ts b/apps/server/src/reports/render/build-assets.ts
index f8ada99e..0c410676 100644
--- a/apps/server/src/reports/render/build-assets.ts
+++ b/apps/server/src/reports/render/build-assets.ts
@@ -6,7 +6,7 @@ import { packageRoot } from '../../package-root.js';
import { buildFonts, fontDir } from './fonts.js';
// The report's build step (D201), run by `pnpm --filter @kept/server build` after tsc:
-// - the eight TTFs, converted from the @ibm/plex-* devDependencies into assets/fonts (fonts.ts);
+// - the eleven TTFs, converted from the @ibm/plex-* devDependencies into assets/fonts (fonts.ts);
// - the files tsc doesn't emit, copied beside the compiled modules that load them: the child
// renderer (child.mjs, plain JavaScript), the Typst templates (report.typ, insurance.typ,
// vehicle.typ, email.typ, condition.typ, move.typ), and the PDF text
diff --git a/apps/server/src/reports/render/fonts.ts b/apps/server/src/reports/render/fonts.ts
index f94c82fc..7706185e 100644
--- a/apps/server/src/reports/render/fonts.ts
+++ b/apps/server/src/reports/render/fonts.ts
@@ -5,11 +5,12 @@ import path from 'node:path';
import { inflateSync } from 'node:zlib';
import { packageRoot } from '../../package-root.js';
-// The report's fonts (D201): IBM Plex Sans, Sans Arabic and Mono, the fonts the web
-// ships. Typst reads only TTF/OTF, and IBM publishes Plex on npm as WOFF/WOFF2 only, so the eight
+// The report's fonts (D201): IBM Plex Sans, Sans Arabic, Sans SC and Mono.
+// Typst reads only TTF/OTF, and IBM publishes Plex on npm as WOFF/WOFF2 only, so the eleven
// faces the template uses are converted at build time (`pnpm --filter @kept/server build` runs
// build-assets.ts) from the pinned devDependencies @ibm/plex-sans@1.1.0,
-// @ibm/plex-sans-arabic@1.1.0 and @ibm/plex-mono@2.5.0 into `assets/fonts/`, with the OFL text.
+// @ibm/plex-sans-arabic@1.1.0, @ibm/plex-sans-sc@1.1.0 and @ibm/plex-mono@2.5.0 into
+// `assets/fonts/`, with the OFL text.
// They are generated, not committed: the repository stays free of binaries, the versions are the
// lockfile's, and check-licences.mjs sees them like any dependency. The image copies the
// directory (Dockerfile); in the repo, a test or a dev server that finds it empty generates it
@@ -19,6 +20,7 @@ import { packageRoot } from '../../package-root.js';
const FACES = [
['@ibm/plex-sans', 'IBMPlexSans', ['Regular', 'Medium', 'SemiBold']],
['@ibm/plex-sans-arabic', 'IBMPlexSansArabic', ['Regular', 'Medium', 'SemiBold']],
+ ['@ibm/plex-sans-sc', 'IBMPlexSansSC', ['Regular', 'Medium', 'SemiBold']],
['@ibm/plex-mono', 'IBMPlexMono', ['Regular', 'SemiBold']],
] as const;
@@ -94,7 +96,7 @@ export function woffToSfnt(woff: Buffer): Buffer {
const hasAll = (dir: string) => FONT_FILES.every((f) => existsSync(path.join(dir, f)));
-/** Converts the eight faces from the @ibm/plex-* packages into `dir`, with the OFL text. Each
+/** Converts the eleven faces from the @ibm/plex-* packages into `dir`, with the OFL text. Each
* file is written under a temp name and renamed, so a reader never sees half a font. */
export async function buildFonts(dir: string = fontDir()): Promise {
const require = createRequire(import.meta.url);
@@ -102,8 +104,11 @@ export async function buildFonts(dir: string = fontDir()): Promise {
for (const [pkg, base, weights] of FACES) {
const root = path.dirname(require.resolve(`${pkg}/package.json`));
for (const w of weights) {
+ const direct = path.join(root, 'fonts', 'complete', 'woff', `${base}-${w}.woff`);
const woff = await readFile(
- path.join(root, 'fonts', 'complete', 'woff', `${base}-${w}.woff`),
+ existsSync(direct)
+ ? direct
+ : path.join(root, 'fonts', 'complete', 'woff', 'hinted', `${base}-${w}.woff`),
);
const dest = path.join(dir, `${base}-${w}.ttf`);
const tmp = `${dest}.${process.pid}.tmp`;
@@ -116,7 +121,7 @@ export async function buildFonts(dir: string = fontDir()): Promise {
let ready: Promise | null = null;
-/** The font directory, with the eight TTFs in it: generated once from node_modules when missing
+/** The font directory, with the eleven TTFs in it: generated once from node_modules when missing
* (the repo), a FontsMissingError when they can't be (an image built without them). */
export function ensureFonts(dir: string = fontDir()): Promise {
if (hasAll(dir)) return Promise.resolve(dir);
diff --git a/apps/server/src/reports/render/render.test.ts b/apps/server/src/reports/render/render.test.ts
index c330a631..1e5820b8 100644
--- a/apps/server/src/reports/render/render.test.ts
+++ b/apps/server/src/reports/render/render.test.ts
@@ -106,11 +106,11 @@ async function jobDir(n: number): Promise {
}
describe('fonts', () => {
- it('converts the eight faces the template asks for, WOFF to TTF byte-exact', async () => {
+ it('converts the eleven faces the template asks for, WOFF to TTF byte-exact', async () => {
const { readFile } = await import('node:fs/promises');
const { existsSync } = await import('node:fs');
await (await import('./fonts.js')).ensureFonts();
- expect(FONT_FILES).toHaveLength(8);
+ expect(FONT_FILES).toHaveLength(11);
for (const f of FONT_FILES) expect(existsSync(path.join(fontDir(), f)), f).toBe(true);
const ttf = await readFile(path.join(fontDir(), 'IBMPlexSansArabic-Regular.ttf'));
expect(ttf.readUInt32BE(0)).toBe(0x00010000); // TrueType
diff --git a/apps/server/src/reports/reports.test.ts b/apps/server/src/reports/reports.test.ts
index 4b4a5580..2e15abc3 100644
--- a/apps/server/src/reports/reports.test.ts
+++ b/apps/server/src/reports/reports.test.ts
@@ -473,6 +473,12 @@ describe('the report job and GET /api/v1/reports/:id', () => {
}
expect(itText).toContain('1.250,50 EGP');
expect(itText).not.toContain('Inventory report');
+ const zh = await report(ann, { scope: { locationId: home.id }, locale: 'zh' });
+ await out('report-zh.pdf', zh.pdf);
+ const zhText = pdfText(zh.pdf);
+ for (const s of ['物品清单报告', '目录', '序列号: SN-TV-0001', tvCode]) {
+ expect(zhText, s).toContain(s);
+ }
});
it('includes ended and trashed things only when asked', async () => {
diff --git a/apps/server/src/reports/routes.ts b/apps/server/src/reports/routes.ts
index 7aef065c..c74f2dfd 100644
--- a/apps/server/src/reports/routes.ts
+++ b/apps/server/src/reports/routes.ts
@@ -35,7 +35,7 @@ import {
// {scope: {locationId} | {accountId},
// filters?: {placeIds?, typeIds?, tagIds?, includeEnded?, includeTrashed?},
// include?: {photos? = true, qr? = false, money? = true},
-// locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi', digits?: 'western' | 'eastern'}
+// locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh', digits?: 'western' | 'eastern'}
// → 202 {id, status: 'queued', expiresAt}; 404 for a scope the caller can't see; 429 past
// five an hour (`retryAfter` seconds in the body and the Retry-After header). With `email: true`,
// 409 `mail_not_configured` on a server without mail, or `no_email_address` for an account with
diff --git a/apps/server/src/reports/template/condition.typ b/apps/server/src/reports/template/condition.typ
index d9d31523..8fb9fa37 100644
--- a/apps/server/src/reports/template/condition.typ
+++ b/apps/server/src/reports/template/condition.typ
@@ -24,7 +24,7 @@
poor: (fill: rgb("#FDF3DC"), ink: rgb("#8A5700")),
damaged: (fill: rgb("#FDECEA"), ink: c.danger),
)
-#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic") }
+#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans", "IBM Plex Sans SC") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic", "IBM Plex Sans SC") }
#let sfx = (w) => if w == 600 { " SmBld" } else if w == 500 { " Medm" } else { "" }
#let W(w) = sans.map(f => f + sfx(w))
#let numpat = if d.digits == "arab" { "١" } else { "1" }
diff --git a/apps/server/src/reports/template/email.typ b/apps/server/src/reports/template/email.typ
index ef3f7942..7b89993e 100644
--- a/apps/server/src/reports/template/email.typ
+++ b/apps/server/src/reports/template/email.typ
@@ -6,7 +6,7 @@
// an Arabic receipt reads right to left.
#let d = json("/data.json")
#let c = (paper: rgb("#FBFAF7"), ink: rgb("#1C1B19"), ink2: rgb("#55524C"), line: rgb("#DEDBD3"))
-#let sans = ("IBM Plex Sans", "IBM Plex Sans Arabic")
+#let sans = ("IBM Plex Sans", "IBM Plex Sans Arabic", "IBM Plex Sans SC")
#set document(title: d.subject)
#set text(font: sans, size: 9.5pt, fill: c.ink, hyphenate: false)
diff --git a/apps/server/src/reports/template/insurance.typ b/apps/server/src/reports/template/insurance.typ
index 3ef8544e..8103da29 100644
--- a/apps/server/src/reports/template/insurance.typ
+++ b/apps/server/src/reports/template/insurance.typ
@@ -17,7 +17,7 @@
ink: rgb("#1C1B19"), ink2: rgb("#55524C"), ink3: rgb("#6B675F"), amber: rgb("#F0B03A"),
amber-ink: rgb("#2E2100"), danger: rgb("#B42318"), danger-bg: rgb("#FDECEA"),
)
-#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic") }
+#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans", "IBM Plex Sans SC") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic", "IBM Plex Sans SC") }
#let mono = "IBM Plex Mono"
#let sfx = (w) => if w == 600 { " SmBld" } else if w == 500 { " Medm" } else { "" }
#let W(w) = sans.map(f => f + sfx(w))
diff --git a/apps/server/src/reports/template/move.typ b/apps/server/src/reports/template/move.typ
index 5d3552c1..e01ccfa4 100644
--- a/apps/server/src/reports/template/move.typ
+++ b/apps/server/src/reports/template/move.typ
@@ -14,7 +14,7 @@
paper: rgb("#FFFFFF"), surface: rgb("#FBFAF7"), sunken: rgb("#ECEAE4"), line: rgb("#DEDBD3"),
ink: rgb("#1C1B19"), ink2: rgb("#55524C"), ink3: rgb("#6B675F"), amber: rgb("#F0B03A"),
)
-#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic") }
+#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans", "IBM Plex Sans SC") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic", "IBM Plex Sans SC") }
#let sfx = (w) => if w == 600 { " SmBld" } else if w == 500 { " Medm" } else { "" }
#let W(w) = sans.map(f => f + sfx(w))
diff --git a/apps/server/src/reports/template/report.typ b/apps/server/src/reports/template/report.typ
index 5deeec46..a60cca68 100644
--- a/apps/server/src/reports/template/report.typ
+++ b/apps/server/src/reports/template/report.typ
@@ -23,7 +23,7 @@
amber-ink: rgb("#2E2100"), amber-text: rgb("#8A5700"), danger: rgb("#B42318"),
dots: rgb("#A8A399"),
)
-#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic") }
+#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans", "IBM Plex Sans SC") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic", "IBM Plex Sans SC") }
#let mono = "IBM Plex Mono"
#let sfx = (w) => if w == 600 { " SmBld" } else if w == 500 { " Medm" } else { "" }
#let W(w) = sans.map(f => f + sfx(w))
diff --git a/apps/server/src/reports/template/vehicle.typ b/apps/server/src/reports/template/vehicle.typ
index 46ec12ab..55820266 100644
--- a/apps/server/src/reports/template/vehicle.typ
+++ b/apps/server/src/reports/template/vehicle.typ
@@ -19,7 +19,7 @@
ink: rgb("#1C1B19"), ink2: rgb("#55524C"), ink3: rgb("#6B675F"), amber: rgb("#F0B03A"),
amber-ink: rgb("#2E2100"), danger: rgb("#B42318"), dots: rgb("#A8A399"),
)
-#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic") }
+#let sans = if isrtl { ("IBM Plex Sans Arabic", "IBM Plex Sans", "IBM Plex Sans SC") } else { ("IBM Plex Sans", "IBM Plex Sans Arabic", "IBM Plex Sans SC") }
#let mono = "IBM Plex Mono"
#let sfx = (w) => if w == 600 { " SmBld" } else if w == 500 { " Medm" } else { "" }
#let W(w) = sans.map(f => f + sfx(w))
@@ -37,7 +37,7 @@
text(font: mono + " SmBld", size: 9pt, tracking: 0.6pt, fill: c.amber-ink, dir: ltr, id))
// The plate: its own island, in the direction it is written in, so its letters keep their order.
#let plate(p, dir) = box(stroke: 1.2pt + c.ink, radius: 3pt, inset: (x: 3mm, y: 1.5mm),
- text(font: ("IBM Plex Sans Arabic SmBld", "IBM Plex Sans SmBld"), size: 13pt, dir: if dir == "rtl" { rtl } else { ltr }, p))
+ text(font: ("IBM Plex Sans Arabic SmBld", "IBM Plex Sans SmBld", "IBM Plex Sans SC SmBld"), size: 13pt, dir: if dir == "rtl" { rtl } else { ltr }, p))
#let vin(v) = box(text(font: mono, size: 10pt, dir: ltr, v))
// ---- Cover.
diff --git a/apps/server/src/reports/words/index.ts b/apps/server/src/reports/words/index.ts
index 6f72932b..70b74a89 100644
--- a/apps/server/src/reports/words/index.ts
+++ b/apps/server/src/reports/words/index.ts
@@ -8,6 +8,7 @@ import { IT } from './it.js';
import type { PdfWords } from './types.js';
import { UK } from './uk.js';
import { VI } from './vi.js';
+import { ZH } from './zh.js';
export type * from './types.js';
@@ -22,4 +23,5 @@ export const PDF_WORDS: Readonly> = {
it: IT,
uk: UK,
vi: VI,
+ zh: ZH,
};
diff --git a/apps/server/src/reports/words/zh.ts b/apps/server/src/reports/words/zh.ts
new file mode 100644
index 00000000..54bf4f7c
--- /dev/null
+++ b/apps/server/src/reports/words/zh.ts
@@ -0,0 +1,256 @@
+import type { PdfWords } from './types.js';
+
+// Simplified Chinese: every PDF's words, following en.ts and the web catalogue's terms (物品, 位置,
+// 地点, 未归置, 序列号). Counts take a classifier (件) with no plural inflection.
+
+const things = (_n: number, f: string) => `${f} 件物品`;
+
+const condition = {
+ new: '全新',
+ good: '良好',
+ fair: '一般',
+ poor: '较差',
+ broken: '损坏',
+};
+
+const lifecycle = {
+ archived: '已归档',
+ sold: '已售出',
+ given_away: '已赠出',
+ lost: '已遗失',
+ disposed: '已处置',
+ stolen: '被盗',
+ destroyed: '已损毁',
+ returned_to_owner: '已归还原主',
+};
+
+const inventory: PdfWords['inventory'] = {
+ title: '物品清单报告',
+ things: '物品',
+ places: '位置',
+ photos: '含照片',
+ totals: '按币种合计',
+ contents: '目录',
+ page: '页码',
+ of: '/',
+ serial: '序列号',
+ subtotal: '小计',
+ bought: '购买日期',
+ confidential: '私密记录:这是你所拥有物品的清单,请像保管这些物品一样妥善保管。',
+ empty: '没有符合此报告条件的物品。',
+ unplaced: '未归置',
+ trashed: '在回收站中',
+ allLocations: '全部地点',
+ locationsList: (names) => `涵盖 ${names}`,
+ generated: (who, when) => `由 ${who} 生成于 ${when}`,
+ moneyPartial: '仅在你可查看金额的地点显示价格。',
+ thingCount: things,
+ filterPlaces: '位置',
+ filterTypes: '类型',
+ filterTags: '标签',
+ withEnded: '包含不再使用的物品',
+ withTrashed: '包含回收站中的物品',
+ condition,
+ lifecycle,
+};
+
+const readable: PdfWords['readable'] = {
+ title: '可读副本',
+ intro:
+ '此地点在 Kept 中保存的全部内容。只需浏览器即可直接打开:照片、收据和文档均可从同目录文件中查看。',
+ exported: (when) => `导出于 ${when}`,
+ places: '位置',
+ things: '物品',
+ photo: '照片',
+ name: '名称',
+ shortId: '短编号',
+ type: '类型',
+ brandModel: '品牌与型号',
+ quantity: '数量',
+ condition: '成色',
+ tags: '标签',
+ lastSeen: '最近确认',
+ files: '文件',
+ inside: '内部物品',
+ ownPage: '独立页面',
+ spreadsheets: '电子表格 (CSV)',
+ pdf: '物品清单报告 (PDF)',
+ pdfLeftOut: (n, max) =>
+ `未附带物品清单报告 (PDF):报告最多容纳 ${things(n, max)}。所有物品均已列于下方及 things.csv 中。`,
+ pdfFailed: '本次未能生成物品清单报告 (PDF)。所有物品均已列于下方。',
+ moneyHidden: '已省略价格:导出此副本的成员无权查看价格。',
+ secretsWithheld: '已省略机密字段值:本次导出未包含机密内容。数据文件中仍保留了相关字段名称。',
+ empty: '此处暂无内容。',
+ fileRole: {
+ photo: '照片',
+ receipt: '收据',
+ invoice: '发票',
+ manual: '说明书',
+ warranty_doc: '保修单',
+ proof: '凭证',
+ condition_out: '借出时状况',
+ condition_in: '归还时状况',
+ registration: '登记证',
+ document: '文档',
+ },
+ conditions: condition,
+ lifecycles: lifecycle,
+};
+
+const insurance: PdfWords['insurance'] = {
+ title: '保险理赔报告',
+ totals: '按币种合计',
+ converted: (ccy) => `折算为 ${ccy}:`,
+ subtotal: '小计',
+ thing: '物品',
+ purchase: '购入',
+ value: '当前价值',
+ receipts: '收据',
+ serial: '序列号',
+ page: '页码',
+ of: '/',
+ empty: '暂无可列出的物品。',
+ asOf: (day) => `截至 ${day}`,
+ owner: (name) => `所有者:${name}`,
+ generated: (who, when) => `由 ${who} 生成于 ${when}`,
+ ratesOf: (days) => `按 ${days} 汇率折算`,
+ purchaseFallback: '未填写估值的物品按购买价格计入。',
+ noMoney: '此地点的金额对你隐藏。',
+ incident: {
+ burglary: '入室盗窃',
+ fire: '火灾',
+ flood: '水灾',
+ loss: '遗失',
+ other: '事故',
+ },
+ police: (ref) => `警方报案编号:${ref}`,
+ insurer: (ref) => `保险理赔编号:${ref}`,
+ occurred: (day) => `发生于 ${day}`,
+};
+
+const conditionReport: PdfWords['condition'] = {
+ title: '房屋状况报告',
+ kinds: { move_in: '入住交接', move_out: '退租交接' },
+ conditions: { good: '良好', fair: '一般', poor: '较差', damaged: '损坏' },
+ notRecorded: '未记录',
+ rooms: '房间',
+ photos: '照片',
+ notes: '备注',
+ page: '页码',
+ of: '/',
+ contents: '目录',
+ confidential: '私密记录:这是该住所的状况记录,请仅与房东或中介共享。',
+ empty: '此报告中没有房间。',
+ notInReport: '未包含在此报告中。',
+ photoNote: '每张照片的时间为 Kept 接收该照片的时间。',
+ draft: '尚未完成:此报告仍可修改。',
+ started: (who) => `由 ${who} 创建`,
+ finished: (who, when) => `由 ${who} 完成于 ${when}`,
+ generated: (who, when) => `由 ${who} 生成于 ${when}`,
+ more: (n) => `Kept 中另有 ${n} 张`,
+};
+
+const move: PdfWords['move'] = {
+ title: '装箱清单',
+ box: (n) => `${n} 号箱`,
+ goesTo: '运往房间',
+ noRoom: '尚未指定房间',
+ contents: (n) => `箱内物品 (${n})`,
+ empty: '此箱暂无物品。',
+ quantity: '数量',
+ id: 'ID',
+ holds: (n) => `内含 ${n} 件`,
+ more: (n) => `Kept 中另有 ${n} 项`,
+ states: { packed: '已装箱', in_transit: '运输中', unpacked: '已拆箱' },
+ route: (from, to) => `${from} → ${to}`,
+ scan: '扫描二维码即可在 Kept 中查看此箱并拆箱。',
+ generated: (who, when) => `由 ${who} 打印于 ${when}`,
+ none: '没有可打印的箱子。',
+};
+
+const vehicle: PdfWords['vehicle'] = {
+ title: '车辆历史报告',
+ cover: {
+ type: '类型',
+ shortId: '短编号',
+ vin: 'VIN',
+ plate: '车牌号',
+ location: '地点',
+ odometer: '里程表',
+ },
+ readings: '里程记录',
+ proofs: '里程表照片',
+ services: '保养维修',
+ fuel: '能耗与补能',
+ documents: '证件文档',
+ date: '日期',
+ reading: '读数',
+ source: '来源',
+ by: '记录人',
+ proof: '照片',
+ item: '项目',
+ qty: '数量',
+ amount: '金额',
+ total: '合计',
+ year: '年份',
+ fills: '加注次数',
+ fuelAmount: '补能量',
+ name: '文档',
+ issued: '签发日期',
+ expires: '到期日期',
+ state: '状态',
+ cost: '费用',
+ page: '页码',
+ of: '/',
+ contents: '目录',
+ confidential: '私密记录:这是单台车辆的档案,请仅分享给需要查看的人。',
+ none: '暂无记录。',
+ readingsCount: '读数记录',
+ servicesCount: '保养次数',
+ proofsCount: '里程照片',
+ documentsCount: '证件文档',
+ consumption: '近 5 次加满平均能耗',
+ perDistance: (unit) => `近 12 个月每 ${unit} 燃料费用`,
+ monthly: '近 12 个月月均燃料费用',
+ noConsumption: '带读数的加满记录尚不足够。',
+ readingsNote:
+ '包含所有带照片或手动输入的读数,以及每月最新读数。加注和保养记录中的读数显示在各自章节中。',
+ sources: {
+ manual: '手动输入',
+ photo: '照片识别',
+ fuel: '加油充电',
+ service: '保养记录',
+ import: '导入',
+ home_assistant: 'Home Assistant',
+ },
+ docKinds: {
+ registration: '行驶证 / 登记证',
+ insurance: '保险单',
+ licence: '牌照许可',
+ inspection: '年检记录',
+ lease: '租赁合同',
+ contract: '合同',
+ },
+ docStates: { current: '有效', expired: '已过期', renewed: '已续期' },
+ units: { L: 'L', kWh: 'kWh', gal: 'gal' },
+ distance: { mi: '英里', h: '小时' },
+ generated: (who, when) => `由 ${who} 生成于 ${when}`,
+ asOf: (day) => `截至 ${day}`,
+ range: (from, to) => `自 ${from} 至 ${to}`,
+ more: (n) => `Kept 中另有 ${n} 张`,
+ moreInvoices: (n) => `+${n}`,
+ moneyHidden: '已省略费用:此地点的金额对你隐藏。',
+ per100: (fuel, distance) => `${fuel}/100 ${distance}`,
+ mpg: (v) => `${v} mpg`,
+ miPerKwh: (v) => `${v} mi/kWh`,
+ perHour: (v, fuel) => `每小时 ${v} ${fuel}`,
+};
+
+export const ZH: PdfWords = {
+ inventory,
+ readable,
+ insurance,
+ condition: conditionReport,
+ move,
+ vehicle,
+};
diff --git a/apps/web/e2e/audit.spec.ts b/apps/web/e2e/audit.spec.ts
index f2ce5148..c9ee152c 100644
--- a/apps/web/e2e/audit.spec.ts
+++ b/apps/web/e2e/audit.spec.ts
@@ -180,7 +180,7 @@ test('the filter strip keeps one row at 375 px in every language', async ({ brow
const location = await p.locator('a[href^="/loc/"]').first().getAttribute('href');
expect(location).toBeTruthy();
const rows: string[] = [];
- for (const lang of ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi']) {
+ for (const lang of ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh']) {
// The page-level script runs after the session's, so this language wins for this page.
const page = await ctx.newPage();
await page.addInitScript((l) => localStorage.setItem('kept.locale', l), lang);
diff --git a/apps/web/index.html b/apps/web/index.html
index 538e014c..dd9040fa 100644
--- a/apps/web/index.html
+++ b/apps/web/index.html
@@ -67,9 +67,9 @@
} catch {}
theme = dark ? 'dark' : 'light';
}
- // The app's languages (D204, and later Spanish, Ukrainian and Vietnamese); the browser's
- // language when it is one of them.
- const locales = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'];
+ // The app's languages (D204, and later Spanish, Ukrainian, Vietnamese and Simplified
+ // Chinese); the browser's language when it is one of them.
+ const locales = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'];
if (!locales.includes(locale)) {
const nav = (navigator.language || 'en').toLowerCase().split(/[-_]/)[0];
locale = locales.includes(nav) ? nav : 'en';
diff --git a/apps/web/lingui.config.ts b/apps/web/lingui.config.ts
index 8a8da49f..acf80520 100644
--- a/apps/web/lingui.config.ts
+++ b/apps/web/lingui.config.ts
@@ -3,7 +3,7 @@ import { formatter } from '@lingui/format-po';
export default defineConfig({
sourceLocale: 'en',
- locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'],
+ locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'],
// PO for translators (D96, Weblate). No line numbers, so catalogues don't churn on every edit.
format: formatter({ lineNumbers: false }),
catalogs: [
diff --git a/apps/web/src/api/condition/types.ts b/apps/web/src/api/condition/types.ts
index 6f875c5e..f9a6a858 100644
--- a/apps/web/src/api/condition/types.ts
+++ b/apps/web/src/api/condition/types.ts
@@ -89,6 +89,6 @@ export type ConditionPdfBody = {
reportId: string;
compareWith?: string;
include?: { photos?: boolean };
- locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+ locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
digits?: 'western' | 'eastern';
};
diff --git a/apps/web/src/api/household/types.ts b/apps/web/src/api/household/types.ts
index 395f4f47..3fed1091 100644
--- a/apps/web/src/api/household/types.ts
+++ b/apps/web/src/api/household/types.ts
@@ -925,7 +925,7 @@ export type InsuranceReportBody = {
/** Needs a rate for every pair, else 409 `rate_missing` with `missing`. */
reportCurrency?: string;
include?: { photos?: boolean };
- locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+ locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
digits?: 'western' | 'eastern';
};
export type InsuranceReportCreated = ReportCreated;
@@ -939,7 +939,7 @@ export type InsuranceCsvParams = ({ locationId: string } | { incidentId: string
/** POST /api/v1/claim-packs. Without `acknowledged` → 400 (D158). */
export type CreateClaimPackBody = {
scope: { incidentId: string } | { locationId: string; thingIds: string[] };
- locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+ locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
digits?: 'western' | 'eastern';
acknowledged: true;
};
diff --git a/apps/web/src/api/inventory/types.ts b/apps/web/src/api/inventory/types.ts
index 9c2aca58..1ee81134 100644
--- a/apps/web/src/api/inventory/types.ts
+++ b/apps/web/src/api/inventory/types.ts
@@ -1692,7 +1692,7 @@ export type InventoryReportBody = {
includeTrashed?: boolean;
};
include?: { photos?: boolean; qr?: boolean; money?: boolean };
- locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+ locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
digits?: 'western' | 'eastern';
/** 1.3 (D228): also mail the PDF to me when it's done. */
email?: boolean;
diff --git a/apps/web/src/api/moving/types.ts b/apps/web/src/api/moving/types.ts
index b97cb5c6..68019ee5 100644
--- a/apps/web/src/api/moving/types.ts
+++ b/apps/web/src/api/moving/types.ts
@@ -90,6 +90,6 @@ export type SheetsPrintedBody = { containerIds?: string[] };
export type ContentsSheetsBody = {
moveId: string;
containerIds?: string[];
- locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+ locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
digits?: 'western' | 'eastern';
};
diff --git a/apps/web/src/api/vehicles/types.ts b/apps/web/src/api/vehicles/types.ts
index 206e7b6a..d8ade572 100644
--- a/apps/web/src/api/vehicles/types.ts
+++ b/apps/web/src/api/vehicles/types.ts
@@ -462,7 +462,7 @@ export type VehicleHistoryReportBody = {
from?: string;
to?: string;
include?: { costs?: boolean; proofPhotos?: boolean; fuel?: boolean; documents?: boolean };
- locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+ locale?: 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
digits?: 'western' | 'eastern';
};
export type VehicleHistoryReportCreated = ReportCreated;
diff --git a/apps/web/src/components/history/labels.test.tsx b/apps/web/src/components/history/labels.test.tsx
index e8b7e4bf..d8dcdf54 100644
--- a/apps/web/src/components/history/labels.test.tsx
+++ b/apps/web/src/components/history/labels.test.tsx
@@ -31,7 +31,7 @@ function All() {
);
}
-describe.each(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'] as const)(
+describe.each(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const)(
'every summary in %s',
(locale) => {
it('is a sentence of its own', async () => {
diff --git a/apps/web/src/components/import/suggest.test.ts b/apps/web/src/components/import/suggest.test.ts
index 8e418a24..0e7de366 100644
--- a/apps/web/src/components/import/suggest.test.ts
+++ b/apps/web/src/components/import/suggest.test.ts
@@ -107,6 +107,26 @@ describe('fields from headers', () => {
['Intitulé', 'name'],
['Artículo', 'name'],
['Producto', 'name'],
+ ['物品名称', 'name'],
+ ['数量', 'quantity'],
+ ['品牌', 'brand'],
+ ['型号', 'model'],
+ ['序列号', 'serial'],
+ ['条形码', 'barcode'],
+ ['颜色', 'colour'],
+ ['成色', 'condition'],
+ ['备注', 'notes'],
+ ['标签', 'tags'],
+ ['位置', 'place_path'],
+ ['类型', 'type'],
+ ['别名', 'aliases'],
+ ['购买日期', 'purchased_on'],
+ ['商家', 'vendor'],
+ ['价格 (CNY)', 'price'],
+ ['币种', 'currency'],
+ ['说明书链接', 'manual_url'],
+ ['资产编号', 'legacy_code'],
+ ['自有编码', 'own_code'],
])('reads %s as %s', (header, field) => {
expect(fieldFromHeader(header)).toBe(field);
});
diff --git a/apps/web/src/components/import/suggest.ts b/apps/web/src/components/import/suggest.ts
index 14e704ed..a3894520 100644
--- a/apps/web/src/components/import/suggest.ts
+++ b/apps/web/src/components/import/suggest.ts
@@ -83,6 +83,11 @@ const WORDS: Record, strin
'sản phẩm',
'tên sản phẩm',
'mặt hàng',
+ '名称',
+ '物品名称',
+ '物品',
+ '商品名称',
+ '品名',
],
quantity: [
'quantity',
@@ -106,6 +111,8 @@ const WORDS: Record, strin
'к-сть',
'số lượng',
'sl',
+ '数量',
+ '件数',
],
brand: [
'brand',
@@ -131,6 +138,9 @@ const WORDS: Record, strin
'hãng',
'nhãn hiệu',
'nhà sản xuất',
+ '品牌',
+ '厂商',
+ '制造商',
],
model: [
'model',
@@ -147,6 +157,8 @@ const WORDS: Record, strin
'kiểu máy',
'mã model',
'mô hình',
+ '型号',
+ '规格型号',
],
serial: [
'serial',
@@ -171,6 +183,8 @@ const WORDS: Record, strin
'số sê-ri',
'số seri',
'số serial',
+ '序列号',
+ '机身编号',
],
barcode: [
'barcode',
@@ -188,8 +202,21 @@ const WORDS: Record, strin
'штрихкод',
'штрих код',
'mã vạch',
+ '条形码',
+ '条码',
+ ],
+ colour: [
+ 'colour',
+ 'color',
+ 'لون',
+ 'couleur',
+ 'farbe',
+ 'colore',
+ 'колір',
+ 'màu sắc',
+ 'màu',
+ '颜色',
],
- colour: ['colour', 'color', 'لون', 'couleur', 'farbe', 'colore', 'колір', 'màu sắc', 'màu'],
condition: [
'condition',
'state',
@@ -203,6 +230,9 @@ const WORDS: Record, strin
'стан',
'tình trạng',
'trạng thái',
+ '成色',
+ '状况',
+ '状态',
],
notes: [
'notes',
@@ -238,6 +268,9 @@ const WORDS: Record, strin
'ghi chú',
'mô tả',
'nhận xét',
+ '备注',
+ '说明',
+ '描述',
],
tags: [
'tags',
@@ -260,6 +293,7 @@ const WORDS: Record, strin
'thẻ',
'nhãn',
'từ khóa',
+ '标签',
],
place_path: [
'place',
@@ -296,6 +330,11 @@ const WORDS: Record, strin
'địa điểm',
'phòng',
'nơi để',
+ '位置',
+ '存放位置',
+ '所在位置',
+ '房间',
+ '位置路径',
],
type: [
'type',
@@ -313,6 +352,9 @@ const WORDS: Record, strin
'категорія',
'loại',
'danh mục',
+ '类型',
+ '分类',
+ '类别',
],
aliases: [
'aliases',
@@ -331,6 +373,8 @@ const WORDS: Record, strin
'псевдоніми',
'tên khác',
'bí danh',
+ '别名',
+ '其他名称',
],
purchased_on: [
'purchase date',
@@ -358,6 +402,8 @@ const WORDS: Record, strin
'придбано',
'дата придбання',
'ngày mua',
+ '购买日期',
+ '购入日期',
],
vendor: [
'vendor',
@@ -391,6 +437,10 @@ const WORDS: Record, strin
'người bán',
'cửa hàng',
'nơi mua',
+ '商家',
+ '店铺',
+ '购买渠道',
+ '卖家',
],
price: [
'price',
@@ -418,6 +468,10 @@ const WORDS: Record, strin
'giá',
'giá mua',
'chi phí',
+ '价格',
+ '购买价格',
+ '单价',
+ '金额',
],
currency: [
'currency',
@@ -430,6 +484,8 @@ const WORDS: Record, strin
'divisa',
'валюта',
'tiền tệ',
+ '币种',
+ '货币',
],
manual_url: [
'manual',
@@ -452,6 +508,9 @@ const WORDS: Record, strin
'посібник користувача',
'sách hướng dẫn',
'hướng dẫn',
+ '说明书',
+ '说明书链接',
+ '使用手册',
],
legacy_code: [
'code',
@@ -482,6 +541,9 @@ const WORDS: Record, strin
'mã',
'mã tài sản',
'số kiểm kê',
+ '资产编号',
+ '原编号',
+ '旧编码',
],
own_code: [
'own code',
@@ -503,6 +565,9 @@ const WORDS: Record, strin
'мій код',
'mã của tôi',
'mã riêng',
+ '自有编码',
+ '自定义编码',
+ '我的编码',
],
source_id: [
'id',
@@ -520,6 +585,8 @@ const WORDS: Record, strin
'ідентифікатор',
'mã định danh',
'tham chiếu',
+ '来源编号',
+ '外部id',
],
};
diff --git a/apps/web/src/components/languages.test.tsx b/apps/web/src/components/languages.test.tsx
index d74ce272..bbb62eaf 100644
--- a/apps/web/src/components/languages.test.tsx
+++ b/apps/web/src/components/languages.test.tsx
@@ -79,6 +79,7 @@ describe('LanguageSelect', () => {
'Italiano',
'Українська',
'Tiếng Việt',
+ '简体中文',
]);
const arabic = screen.getByRole('option', { name: 'العربية' });
expect(arabic.querySelector('[lang="ar"]')).toHaveAttribute('dir', 'rtl');
@@ -109,6 +110,8 @@ describe('LanguageSelect', () => {
['espanol', 'Español'],
['العربية', 'العربية'],
['arabic', 'العربية'],
+ ['中文', '简体中文'],
+ ['chinese', '简体中文'],
])('finds "%s" and shows only %s', async (query, name) => {
const { user } = await renderUI();
const box = screen.getByRole('combobox');
diff --git a/apps/web/src/components/languages.tsx b/apps/web/src/components/languages.tsx
index 3c8d3f7f..d09f020e 100644
--- a/apps/web/src/components/languages.tsx
+++ b/apps/web/src/components/languages.tsx
@@ -8,6 +8,7 @@
import { findLanguages, languageSearch } from '@kept/shared';
import { useLingui } from '@lingui/react/macro';
+import CN from 'country-flag-icons/react/3x2/CN';
import DE from 'country-flag-icons/react/3x2/DE';
import EG from 'country-flag-icons/react/3x2/EG';
import ES from 'country-flag-icons/react/3x2/ES';
@@ -37,6 +38,7 @@ export const LANGUAGE_NAMES: Readonly> = {
it: 'Italiano',
uk: 'Українська',
vi: 'Tiếng Việt',
+ zh: '简体中文',
};
const FLAGS: Readonly> = {
@@ -48,6 +50,7 @@ const FLAGS: Readonly> = {
it: IT,
uk: UA,
vi: VN,
+ zh: CN,
};
export const LANGUAGES: readonly Language[] = LOCALES.map((id) => ({
diff --git a/apps/web/src/i18n/catalogue-words.test.ts b/apps/web/src/i18n/catalogue-words.test.ts
index 4e1f63c0..5a9432c9 100644
--- a/apps/web/src/i18n/catalogue-words.test.ts
+++ b/apps/web/src/i18n/catalogue-words.test.ts
@@ -22,6 +22,7 @@ describe('the catalogues', () => {
['es', 'Tabla', 'Enlace del manual'],
['uk', 'Таблиця', 'Посилання на інструкцію'],
['vi', 'Bảng', 'Liên kết sách hướng dẫn'],
+ ['zh', '表格', '说明书链接'],
])('%s writes the layout and the manual link for what they are', (locale, table, manual) => {
const words = entries(locale);
expect(words.get('Table')).toBe(table);
diff --git a/apps/web/src/i18n/i18n.ts b/apps/web/src/i18n/i18n.ts
index fbae51e1..2c57aaca 100644
--- a/apps/web/src/i18n/i18n.ts
+++ b/apps/web/src/i18n/i18n.ts
@@ -23,6 +23,7 @@ const loaders: Record Promise<{ messages: Messages }>> = {
it: () => import('../locales/it/messages.po'),
uk: () => import('../locales/uk/messages.po'),
vi: () => import('../locales/vi/messages.po'),
+ zh: () => import('../locales/zh/messages.po'),
};
/**
diff --git a/apps/web/src/lib/amount.test.ts b/apps/web/src/lib/amount.test.ts
index ae250845..1d430a2c 100644
--- a/apps/web/src/lib/amount.test.ts
+++ b/apps/web/src/lib/amount.test.ts
@@ -18,7 +18,18 @@ describe('amount fields read and write by the reader’s language (#474)', () =>
expect(amountText('1234.5', 'ar-u-nu-arab')).toBe('١٢٣٤٫٥');
expect(amountText(null, 'de')).toBe('');
expect(amountText('not money', 'de')).toBe('not money');
- for (const tag of ['ar-u-nu-arab', 'ar-u-nu-latn', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi']) {
+ for (const tag of [
+ 'ar-u-nu-arab',
+ 'ar-u-nu-latn',
+ 'de',
+ 'en',
+ 'es',
+ 'fr',
+ 'it',
+ 'uk',
+ 'vi',
+ 'zh',
+ ]) {
for (const amount of ['0.5', '1.234', '12.345', '1234', '12345.6789']) {
expect([tag, readAmount(amountText(amount, tag), tag)]).toEqual([tag, amount]);
}
diff --git a/apps/web/src/lib/prefs.test.ts b/apps/web/src/lib/prefs.test.ts
index 98f6e3de..6cb3e821 100644
--- a/apps/web/src/lib/prefs.test.ts
+++ b/apps/web/src/lib/prefs.test.ts
@@ -40,16 +40,19 @@ afterEach(() => {
describe('languages', () => {
it('has the languages, and knows a tag by its language', () => {
- expect(LOCALES).toEqual(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi']);
+ expect(LOCALES).toEqual(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh']);
expect(isLocale('it')).toBe(true);
expect(isLocale('vi')).toBe(true);
expect(isLocale('uk')).toBe(true);
expect(isLocale('es')).toBe(true);
+ expect(isLocale('zh')).toBe(true);
expect(isLocale('pt')).toBe(false);
expect(localeOfTag('ar-EG')).toBe('ar');
expect(localeOfTag('fr_CA')).toBe('fr');
expect(localeOfTag('DE-at')).toBe('de');
expect(localeOfTag('es-ES')).toBe('es');
+ expect(localeOfTag('zh-CN')).toBe('zh');
+ expect(localeOfTag('zh-Hans-CN')).toBe('zh');
expect(localeOfTag('pt-BR')).toBeNull();
});
diff --git a/apps/web/src/lib/prefs.ts b/apps/web/src/lib/prefs.ts
index a05fcc26..1e81d0a7 100644
--- a/apps/web/src/lib/prefs.ts
+++ b/apps/web/src/lib/prefs.ts
@@ -9,7 +9,7 @@ import { useSyncExternalStore } from 'react';
export type ThemePref = 'light' | 'dark' | 'system';
/** D204: the launch languages. Arabic is the only right-to-left one. */
-export type Locale = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+export type Locale = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
/** D143: in Arabic, Western (0123) or Eastern Arabic (٠١٢٣) digits. Other languages are always Western. */
export type Digits = 'western' | 'eastern';
/** D203: page content in the readable column (the default) or across the whole space. */
@@ -38,7 +38,7 @@ export const DIGITS_KEY = 'kept.digits';
export const WIDTH_KEY = 'kept.width';
export const REGION_KEY = 'kept.region';
export const DATE_FORMAT_KEY = 'kept.dateFormat';
-export const LOCALES: readonly Locale[] = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'];
+export const LOCALES: readonly Locale[] = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'];
export function isLocale(value: unknown): value is Locale {
return typeof value === 'string' && (LOCALES as readonly string[]).includes(value);
diff --git a/apps/web/src/locales/zh/messages.po b/apps/web/src/locales/zh/messages.po
new file mode 100644
index 00000000..3fa05990
--- /dev/null
+++ b/apps/web/src/locales/zh/messages.po
@@ -0,0 +1,20991 @@
+msgid ""
+msgstr ""
+"POT-Creation-Date: 2026-09-26 04:23+0300\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: @lingui/cli\n"
+"Language: zh\n"
+
+msgid " and "
+msgstr " 和 "
+
+msgid ", "
+msgstr ","
+
+msgid "Home Assistant backs up Kept"
+msgstr "由 Home Assistant 备份 Kept"
+
+msgid "Home Assistant backs up Kept: the database, photos and files, and Kept's keys. Take or schedule backups in Home Assistant → {place}."
+msgstr "Home Assistant 会备份 Kept 的数据库、照片与文件以及密钥。请在 Home Assistant → {place} 中手动备份或设置定时备份。"
+
+msgid "Settings → System → Backups"
+msgstr "设置 → 系统 → 备份"
+
+msgid "Home Assistant backs up Kept here: take or schedule backups in Home Assistant."
+msgstr "Kept 由 Home Assistant 负责备份:请在 Home Assistant 中手动备份或设置定时备份。"
+
+msgid "Take or schedule them in Home Assistant → {place}."
+msgstr "请在 Home Assistant → {place} 中执行或定时安排。"
+
+msgid "Location name"
+msgstr "空间名称"
+
+msgid "Renamed to {trimmed}"
+msgstr "已重命名为 {trimmed}"
+
+msgid "Set up email"
+msgstr "配置邮件"
+
+msgid "Without it, Kept sends no sign-in links, password resets, email invites or reminders."
+msgstr "未配置时,Kept 将无法发送登录链接、密码重置、邮件邀请或提醒。"
+
+msgid "Any provider that offers SMTP works, such as your email provider's app password or a sending service. Admin → Status shows Sending once it's on."
+msgstr "任何支持 SMTP 的服务商均可使用,例如邮箱服务商的应用专用密码或专门的发信服务。配置启用后,「管理 → 状态」会显示“正在发送”。"
+
+msgid "the sender, for example <0>Kept 0>"
+msgstr "发件人,例如 <0>Kept 0>"
+
+msgid "your mail server, for example <0>smtps://user:password@smtp.example.org:4650>"
+msgstr "你的邮件服务器,例如 <0>smtps://user:password@smtp.example.org:4650>"
+
+msgid "(a place)"
+msgstr "(一个位置)"
+
+msgid "(a thing)"
+msgstr "(一件物品)"
+
+msgid "(empty)"
+msgstr "(空)"
+
+msgid "(in use)"
+msgstr "(使用中)"
+
+msgid "(changed)"
+msgstr "(已变更)"
+
+msgid "(this one)"
+msgstr "(当前)"
+
+msgid "{0, plural, one {# capture} other {# captures}}"
+msgstr "{0, plural, one {# 次采集} other {# 次采集}}"
+
+msgid "{0, plural, one {# photo} other {# photos}}"
+msgstr "{0, plural, one {# 张照片} other {# 张照片}}"
+
+msgid "{0, plural, one {# place} other {# places}}"
+msgstr "{0, plural, one {# 个位置} other {# 个位置}}"
+
+msgid "{0, plural, =0 {no fields} one {# field} other {# fields}}"
+msgstr "{0, plural, =0 {无字段} one {# 个字段} other {# 个字段}}"
+
+msgid "Set these where Kept's other settings live (the .env file with Docker Compose; with the Helm chart, the URL in the secret named by smtp.existingSecret and the sender in smtp.from), then restart Kept:"
+msgstr "请在 Kept 的配置文件中设置以下环境变量(Docker Compose 为 .env 文件;Helm Chart 为 smtp.existingSecret 指定 Secret 中的 URL 以及 smtp.from 发件人),然后重启 Kept:"
+
+msgid "the request was more than the plan allows in one minute"
+msgstr "请求超出了套餐每分钟限额"
+
+msgid "…this one"
+msgstr "…此项"
+
+msgid "· inherited"
+msgstr "· 继承"
+
+msgid "“{clash}” is already a field of this type, one it inherits from, or one below it. Pick another key."
+msgstr "「{clash}」已是此类型、其父类型或子类型的字段。请更换其他键名。"
+
+msgid "“<0>{0}0>” can mean more than one currency. Which was it?"
+msgstr "“<0>{0}0>”可能对应多种货币,请问是指哪一种?"
+
+msgid "“$” alone can mean US or Canadian dollars. Which was it?"
+msgstr "单独的“$”可能指美元或加元,请问是指哪一种?"
+
+msgid "{0, plural, one {# chosen} other {# chosen}}"
+msgstr "{0, plural, one {已选 # 项} other {已选 # 项}}"
+
+msgid "{0, plural, one {# line} other {# lines}}"
+msgstr "{0, plural, one {# 行} other {# 行}}"
+
+msgid "{0, plural, one {# moved in} other {# moved in}}"
+msgstr "{0, plural, one {# 项已移入} other {# 项已移入}}"
+
+msgid "{0, plural, one {# not here} other {# not here}}"
+msgstr "{0, plural, one {# 项不在此处} other {# 项不在此处}}"
+
+msgid "{0, plural, one {# of them} other {# of them}}"
+msgstr "{0, plural, one {其中 # 项} other {其中 # 项}}"
+
+msgid "{0, plural, one {# other change goes too.} other {# other changes go too.}}"
+msgstr "{0, plural, one {另有 # 项更改也将一并移除。} other {另有 # 项更改也将一并移除。}}"
+
+msgid "{0, plural, one {# partly here: the rest is marked not here} other {# partly here: the rest is marked not here}}"
+msgstr "{0, plural, one {# 项部分在场:其余已标记为不在此处} other {# 项部分在场:其余已标记为不在此处}}"
+
+msgid "{0, plural, one {# scan from while you were offline} other {# scans from while you were offline}}"
+msgstr "{0, plural, one {离线期间的 # 次扫码} other {离线期间的 # 次扫码}}"
+
+msgid "{0, plural, one {# seen} other {# seen}}"
+msgstr "{0, plural, one {已盘点 #} other {已盘点 #}}"
+
+msgid "{0, plural, one {# thing uses it} other {# things use it}}"
+msgstr "{0, plural, one {# 件物品使用它} other {# 件物品使用它}}"
+
+msgid "{0, plural, one {# thing} other {# things}}"
+msgstr "{0, plural, one {# 件物品} other {# 件物品}}"
+
+msgid "{0, plural, one {Also affects # location you can't see.} other {Also affects # locations you can't see.}}"
+msgstr "{0, plural, one {同时影响 # 个你无权查看的空间。} other {同时影响 # 个你无权查看的空间。}}"
+
+msgid "{0, plural, one {Box inside · # thing, not opened} other {Box inside · # things, not opened}}"
+msgstr "{0, plural, one {内有箱子 · # 件物品,尚未打开} other {内有箱子 · # 件物品,尚未打开}}"
+
+msgid "{0, plural, one {Carrying #} other {Carrying #}}"
+msgstr "{0, plural, one {正携带 #} other {正携带 #}}"
+
+msgid "{0, plural, one {Kept # file} other {Kept # files}}"
+msgstr "{0, plural, one {保留了 # 份文件} other {保留了 # 份文件}}"
+
+msgid "{0, plural, one {Move # here} other {Move # here}}"
+msgstr "{0, plural, one {将 # 项移至此处} other {将 # 项移至此处}}"
+
+msgid "{0, plural, one {Move # thing to…} other {Move # things to…}}"
+msgstr "{0, plural, one {将 # 件物品移至…} other {将 # 件物品移至…}}"
+
+msgid "{0, plural, one {Moved # thing to {1}} other {Moved # things to {2}}}"
+msgstr "{0, plural, one {已将 # 件物品移至 {1}} other {已将 # 件物品移至 {2}}}"
+
+msgid "{0, plural, one {Moved # thing to {where}} other {Moved # things to {where}}}"
+msgstr "{0, plural, one {已将 # 件物品移至 {where}} other {已将 # 件物品移至 {where}}}"
+
+msgid "{0, plural, one {Name # unnamed photo} other {Name # unnamed photos}}"
+msgstr "{0, plural, one {命名 # 张未命名照片} other {命名 # 张未命名照片}}"
+
+msgid "{0, plural, one {raised once} other {raised # times}}"
+msgstr "{0, plural, one {触发过 1 次} other {触发过 # 次}}"
+
+msgid "{0, plural, one {Show everyone's (#)} other {Show everyone's (#)}}"
+msgstr "{0, plural, one {显示所有人的(#)} other {显示所有人的(#)}}"
+
+msgid "{0} {unit} doesn't fit the readings around it"
+msgstr "{0} {unit} 与前后读数不符"
+
+msgid "{0} {unit} is higher than {1} on {2}"
+msgstr "{0} {unit} 高于 {2} 的 {1}"
+
+msgid "{0} {unit} is lower than {1} on {2}"
+msgstr "{0} {unit} 低于 {2} 的 {1}"
+
+msgid "{0} × {price}"
+msgstr "{0} × {price}"
+
+msgid "{0} and {1} others will lose sight of it."
+msgstr "{0} 及另外 {1} 人将无法再查看它。"
+
+msgid "{0} couldn't be changed"
+msgstr "无法更改 {0}"
+
+msgid "{0} has things in it"
+msgstr "{0} 中包含物品"
+
+msgid "{0} is in Trash"
+msgstr "{0} 已在回收站中"
+
+msgid "{0} months"
+msgstr "{0} 个月"
+
+msgid "{0} more fields for this type are empty. Edit to fill them in."
+msgstr "此类型还有 {0} 个字段为空。点击编辑即可填写。"
+
+msgid "{0} of {1} ticked"
+msgstr "已勾选 {0} / {1}"
+
+msgid "{0} on"
+msgstr "{0} 项开启"
+
+msgid "{0} stays on: a location uses it."
+msgstr "{0} 将保持启用:已有空间在使用它。"
+
+msgid "{0} stays on: it's one of the five defaults."
+msgstr "{0} 将保持开启:它是五个默认项之一。"
+
+msgid "{0} things are inside. What should happen to them?"
+msgstr "内部有 {0} 件物品,如何处理?"
+
+msgid "{0} to review"
+msgstr "{0} 项待审核"
+
+msgid "{0} will lose sight of it."
+msgstr "{0} 将无法再看到它。"
+
+msgid "{0}'s account"
+msgstr "{0} 的账号"
+
+msgid "{alerts} open"
+msgstr "{alerts} 项待处理"
+
+msgid "{browser} on {where}"
+msgstr "{where} 上的 {browser}"
+
+msgid "{captured, plural, one {# captured} other {# captured}}"
+msgstr "{captured, plural, one {已采集 # 项} other {已采集 # 项}}"
+
+msgid "{captures} and {photos} were taken on this phone by someone who has signed out. They can't go to your account, so they will be deleted."
+msgstr "这台手机上有已退出登录的其他用户拍摄的 {captures} 和 {photos}。这些内容无法转入你的账号,将被删除。"
+
+msgid "{code} is off"
+msgstr "{code} 已停用"
+
+msgid "{code} is on"
+msgstr "{code} 已开启"
+
+msgid "{count, plural, one {# file arrived.} other {# files arrived.}}"
+msgstr "{count, plural, one {已收到 # 个文件。} other {已收到 # 个文件。}}"
+
+msgid "{count, plural, one {Carrying #} other {Carrying #}}"
+msgstr "{count, plural, one {已携带 # 项} other {已携带 # 项}}"
+
+msgid "{count} drafts"
+msgstr "{count} 份草稿"
+
+msgid "{count} found"
+msgstr "已找到 {count} 项"
+
+msgid "{countText}+"
+msgstr "{countText}+"
+
+msgid "{createdName} is ready"
+msgstr "{createdName} 已就绪"
+
+msgid "{done} of {total}"
+msgstr "{done} / {total}"
+
+msgid "{first} will lose sight of {it}."
+msgstr "{first} 将无法再查看{it}。"
+
+msgid "{group} group"
+msgstr "{group} 字段组"
+
+msgid "{group} group · shared by {shared}"
+msgstr "{group} 字段组 · 共享者:{shared}"
+
+msgid "{inviter} invites you to"
+msgstr "{inviter} 邀请你加入"
+
+msgid "{label} saved"
+msgstr "{label} 已保存"
+
+msgid "{label}, inherited"
+msgstr "{label}(继承)"
+
+msgid "{label}: {summary}"
+msgstr "{label}:{summary}"
+
+msgid "{label}: not {summary}"
+msgstr "{label}:非 {summary}"
+
+msgid "{links, plural, one {Accept the receipt and # link} other {Accept the receipt and # links}}"
+msgstr "{links, plural, one {确认收据并关联 # 项} other {确认收据并关联 # 项}}"
+
+msgid "{mb} MB"
+msgstr "{mb} MB"
+
+msgid "{mergedFrom}'s other changes were kept too."
+msgstr "{mergedFrom} 的其他变更也已一并保留。"
+
+msgid "{missing, plural, one {# will be marked not here} other {# will be marked not here}}"
+msgstr "{missing, plural, one {# 项将被标记为不在此处} other {# 项将被标记为不在此处}}"
+
+msgid "{more, plural, one {# more icon matches. Type more to narrow.} other {# more icons match. Type more to narrow.}}"
+msgstr "{more, plural, one {还有 # 个匹配的图标。继续输入以缩小范围。} other {还有 # 个匹配的图标。继续输入以缩小范围。}}"
+
+msgid "{moved, plural, one {# thing has a place now.} other {# things have a place now.}}"
+msgstr "{moved, plural, one {# 件物品已有存放位置。} other {# 件物品已有存放位置。}}"
+
+msgid "{n, plural, one {# captured into {where}} other {# captured into {where}}}"
+msgstr "{n, plural, one {已采集 # 项至 {where}} other {已采集 # 项至 {where}}}"
+
+msgid "{n, plural, one {# captured} other {# captured}}"
+msgstr "{n, plural, one {已录入 # 项} other {已录入 # 项}}"
+
+msgid "{n, plural, one {# person} other {# people}}"
+msgstr "{n, plural, one {# 人} other {# 人}}"
+
+msgid "{n, plural, one {# reading needs a look} other {# readings need a look}}"
+msgstr "{n, plural, one {# 条读数需核对} other {# 条读数需核对}}"
+
+msgid "{n, plural, one {# selected} other {# selected}}"
+msgstr "{n, plural, one {已选 # 项} other {已选 # 项}}"
+
+msgid "{n, plural, one {# thing} other {# things}}"
+msgstr "{n, plural, one {# 件物品} other {# 件物品}}"
+
+msgid "{n, plural, one {Move # here} other {Move # here}}"
+msgstr "{n, plural, one {将 # 项移至此处} other {将 # 项移至此处}}"
+
+msgid "{n, plural, one {Naming # photo} other {Naming # photos}}"
+msgstr "{n, plural, one {正在为 # 张照片命名} other {正在为 # 张照片命名}}"
+
+msgid "{n, plural, one {Put the thing you're carrying here?} other {Put the # things you're carrying here?}}"
+msgstr "{n, plural, one {将携带的这件物品放到这里?} other {将携带的这 # 件物品放到这里?}}"
+
+msgid "{n} failed in the last hour."
+msgstr "过去一小时内有 {n} 项失败。"
+
+msgid "{n} lines to link"
+msgstr "待关联 {n} 条明细"
+
+msgid "{n} rows in audit_events_default. Move them into their month's partition as kept_owner; the alert then resolves."
+msgstr "audit_events_default 中存在 {n} 行记录。请以 kept_owner 身份将其移入对应月份的分区,随后此告警会自动解除。"
+
+msgid "{name} · Location settings"
+msgstr "{name} · 空间设置"
+
+msgid "{name} asks for two-factor. You can join now; it stays hidden until you add a passkey or an authenticator app."
+msgstr "{name} 要求开启双重验证。你现在可以先加入;但在你添加通行密钥或身份验证器应用前,该空间内容将保持隐藏。"
+
+msgid "{name} is a box now"
+msgstr "{name} 已设为收纳箱"
+
+msgid "{name} is empty"
+msgstr "{name} 为空"
+
+msgid "{name} is in the trash"
+msgstr "{name} 在回收站中"
+
+msgid "{name} is in use: things or types below it still use it. Merge it into another type instead."
+msgstr "{name} 正在使用中:仍有物品或子类型引用它。请改为将其合并到其他类型。"
+
+msgid "{name} is now your account's own"
+msgstr "{name} 现已归属你的账号"
+
+msgid "{name} is now your account's own type"
+msgstr "{name} 现已设为你的账号专属类型"
+
+msgid "{name} is still used by some things. Merge it into another instead."
+msgstr "{name} 仍被部分物品使用,请改用合并功能将其并入其他项。"
+
+msgid "{name} restored"
+msgstr "已恢复 {name}"
+
+msgid "{name}, {extra}"
+msgstr "{name},{extra}"
+
+msgid "{name}: how many you found, out of {total}"
+msgstr "{name}:已找到的数量(共 {total} 件)"
+
+msgid "{others, plural, one {{first} and # other will lose sight of {it}.} other {{first} and # others will lose sight of {it}.}}"
+msgstr "{others, plural, one {{first} 及另外 # 人将无法再看到 {it}。} other {{first} 及另外 # 人将无法再看到 {it}。}}"
+
+msgid "{others, plural, one {with # other} other {with # others}}"
+msgstr "{others, plural, one {及另外 # 人} other {及另外 # 人}}"
+
+msgid "{person} signs in with the username below and this one-time code, then chooses their own password. You never see it. The code works once, for 30 minutes."
+msgstr "{person} 可使用下方用户名和此一次性登录码登录,随后自行设置密码,你不会看到对方密码。此码单次有效,有效期 30 分钟。"
+
+msgid "{place} asks everyone for two-factor. They can join now; {place} stays hidden for them until they add a passkey or an authenticator."
+msgstr "{place} 要求所有成员启用双重验证。他们现在即可加入,但在添加通行密钥或验证器前,{place} 会对其保持隐藏。"
+
+msgid "{places, plural, one {# place} other {# places}}"
+msgstr "{places, plural, one {# 个位置} other {# 个位置}}"
+
+msgid "{provider} isn't answering · retrying at {0}"
+msgstr "{provider} 无响应 · 将于 {0} 重试"
+
+msgid "{provider} rejected the key · Replace it in AI settings"
+msgstr "{provider} 拒绝了该密钥 · 请在 AI 设置中更换"
+
+msgid "{repointed, plural, one {# thing changed type.} other {# things changed type.}}"
+msgstr "{repointed, plural, one {# 件物品已更改类型。} other {# 件物品已更改类型。}}"
+
+msgid "{repointed, plural, one {# thing updated.} other {# things updated.}}"
+msgstr "{repointed, plural, one {已更新 # 件物品。} other {已更新 # 件物品。}}"
+
+msgid "{role} invite"
+msgstr "{role}邀请"
+
+msgid "{role} until {until}"
+msgstr "{role},有效期至 {until}"
+
+msgid "{seen} receipt"
+msgstr "{seen} 收据"
+
+msgid "{synced, plural, one {# synced} other {# synced}}"
+msgstr "{synced, plural, one {已同步 # 项} other {已同步 # 项}}"
+
+msgid "{target} belongs to someone else's account: its type, tags and purchase are copied there."
+msgstr "{target} 属于其他人的账号:其类型、分类标签和购买记录将复制到该账号中。"
+
+msgid "{thingName} · {meterName}"
+msgstr "{thingName} · {meterName}"
+
+msgid "{things, plural, one {# thing} other {# things}}"
+msgstr "{things, plural, one {# 件物品} other {# 件物品}}"
+
+msgid "{unnamed, plural, one {and # more} other {and # more}}"
+msgstr "{unnamed, plural, one {以及另外 # 项} other {以及另外 # 项}}"
+
+msgid "{unplaced, plural, one {# thing needs a place} other {# things need a place}}"
+msgstr "{unplaced, plural, one {# 件物品尚未指定位置} other {# 件物品尚未指定位置}}"
+
+msgid "{unsynced, plural, one {# capture hasn't synced. Signing out deletes it.} other {# captures haven't synced. Signing out deletes them.}}"
+msgstr "{unsynced, plural, one {有 # 条采集尚未同步,退出登录将会删除该记录。} other {有 # 条采集尚未同步,退出登录将会删除这些记录。}}"
+
+msgid "{v} receipt"
+msgstr "{v} 收据"
+
+msgid "{vendor} receipt"
+msgstr "{vendor} 收据"
+
+msgid "{waiting, plural, one {# waiting to sync} other {# waiting to sync}}"
+msgstr "{waiting, plural, one {# 项等待同步} other {# 项等待同步}}"
+
+msgid "{waiting, plural, one {Open to finish syncing (#).} other {Open to finish syncing (#).}}"
+msgstr "{waiting, plural, one {打开以完成同步(#)。} other {打开以完成同步(#)。}}"
+
+msgid "{when} · {count} captured · <0>{where}0>"
+msgstr "{when} · 已录入 {count} 件 · <0>{where}0>"
+
+msgid "{who} (you)"
+msgstr "{who}(你)"
+
+msgid "{who} can disable accounts, change sign-up and see failed jobs and alerts, but not other people's locations. They get an email about it."
+msgstr "{who} 可以停用账号、更改注册设置以及查看失败的任务与告警,但无法查看他人的空间。对方会收到邮件通知。"
+
+msgid "{who} can sign in again. They get an email about it."
+msgstr "{who} 现已可重新登录。对方会收到邮件通知。"
+
+msgid "{who} changed it to <0>{theirs}0>; you have <1>{mine}1>."
+msgstr "{who} 已将其更改为 <0>{theirs}0>;你当前保留的是 <1>{mine}1>。"
+
+msgid "{who} changed these since you opened them"
+msgstr "{who} 在你打开后修改了这些内容"
+
+msgid "{who} changed this since you opened it"
+msgstr "自你打开此页后,{who} 修改了此内容"
+
+msgid "{who} changed this type since you opened it. Reload to see their change, then make yours again."
+msgstr "{who} 在你打开后修改了此类型。请刷新以查看对方更改,然后再重新提交你的修改。"
+
+msgid "{who} is no longer an instance admin"
+msgstr "{who} 已不再是实例管理员"
+
+msgid "{who} is now an instance admin. They get an email about it."
+msgstr "{who} 现已成为实例管理员,系统会向其发送邮件通知。"
+
+msgid "{who} is signed out everywhere and can't sign in until you enable the account again. Their locations and things stay. They get an email about it."
+msgstr "{who} 已在所有设备上退出登录,且在重新启用账号前无法登录。其名下的空间与物品将保留。对方会收到邮件通知。"
+
+msgid "{who} is signed out on every device and sets a new password with the code. Any earlier code stops working."
+msgstr "{who} 已在所有设备上退出登录,需使用此重置码设置新密码。此前生成的所有重置码均已失效。"
+
+msgid "{who} keeps their own locations and things, and loses this admin area. They get an email about it."
+msgstr "{who} 将保留其自己的空间和物品,但会失去此管理区域权限,并会收到一封相关邮件。"
+
+msgid "{who} loses access straight away. What {who} added stays. Their webhooks, share links and exports for {place} stop working."
+msgstr "{who} 将立即失去访问权限。{who} 添加的内容会保留,但其在 {place} 的 Webhook、分享链接和导出任务将停止工作。"
+
+msgid "{who} removed from {place}"
+msgstr "已将 {who} 从 {place} 移除"
+
+msgid "{who} signs in with their username and this code, then chooses a new password. It is shown only now. Works once, until {validUntil}."
+msgstr "{who} 使用其用户名和此验证码登录后,即可设置新密码。此验证码仅显示这一次,单次有效,有效期至 {validUntil}。"
+
+msgid "{who}'s"
+msgstr "{who} 的"
+
+msgid "{who}'s monthly cap reached"
+msgstr "已达到 {who} 的月度上限"
+
+msgid "{who}'s monthly token limit reached"
+msgstr "{who} 已达到本月 token 限额"
+
+msgid "+ page to this receipt"
+msgstr "+ 为此收据添加一页"
+
+msgid "+ photo to this thing"
+msgstr "+ 为此物品添加照片"
+
+msgid "× {0}"
+msgstr "× {0}"
+
+msgid "<0>{0}0> · {when}"
+msgstr "<0>{0}0> · {when}"
+
+msgid "<0>{0}0> has {inside} inside. What should happen to them?"
+msgstr "<0>{0}0> 里面还有 {inside}。要怎么处理里面的内容?"
+
+msgid "<0>{0}0> is already in this list"
+msgstr "<0>{0}0> 已在此列表中"
+
+msgid "<0>{0}0> is empty"
+msgstr "<0>{0}0> 为空"
+
+msgid "<0>{0}0> selected"
+msgstr "已选 <0>{0}0> 项"
+
+msgid "<0>{entity}0> was trashed by <1>{by}1>."
+msgstr "<0>{entity}0> 已被 <1>{by}1> 移入回收站。"
+
+msgid "<0>{seen}0> receipt"
+msgstr "<0>{seen}0> 份收据"
+
+msgid "<0>{thingName}0> · {meterName}"
+msgstr "<0>{thingName}0> · {meterName}"
+
+msgid "<0>{timezone} · {currency}0> from this device. Change these and single modules in Location settings."
+msgstr "取自当前设备:<0>{timezone} · {currency}0>。可在「空间设置」中更改这些信息与单个模块。"
+
+msgid "<0>{vendor}0> receipt"
+msgstr "<0>{vendor}0> 收据"
+
+msgid "<0>Asset {legacy}0> is on more than one thing you brought from Homebox. Pick the one in your hands."
+msgstr "<0>资产 {legacy}0> 出现在你从 Homebox 导入的多件物品上。请选择你手上的那件。"
+
+msgid "1 line to link"
+msgstr "1 行待关联"
+
+msgid "3 to 32 characters: lowercase letters, digits, dot, dash or underscore."
+msgstr "3 至 32 个字符:支持小写字母、数字、点、短横线或下划线。"
+
+msgid "6 characters, printed as <0>KEPT SETUP CODE: K7Q-2M90>. The dash is optional; case doesn't matter."
+msgstr "6 位字符,打印格式为 <0>KEPT SETUP CODE: K7Q-2M90>。短横线可省略,不区分大小写。"
+
+msgid "6-digit code"
+msgstr "6 位验证码"
+
+msgid "A bigger jump than it could make"
+msgstr "变化幅度超出合理范围"
+
+msgid "a box"
+msgstr "一个箱子"
+
+msgid "A box is a thing: it can be moved, with everything in it, in one step. <0>{name}0> keeps its ID and label, and what's in it stays in it."
+msgstr "收纳箱本身也是一件物品:可以连同其中的一切一次性移动。<0>{name}0> 会保留自己的 ID 和标签,箱内物品也会保持在箱中。"
+
+msgid "a brand"
+msgstr "品牌"
+
+msgid "A change couldn't apply"
+msgstr "有一项更改未能应用"
+
+msgid "A change made offline couldn't apply"
+msgstr "有一项离线更改未能应用"
+
+msgid "A computer: the camera icon in the address bar, then Allow."
+msgstr "电脑端:点击地址栏中的相机图标,然后选择「允许」。"
+
+msgid "A contact, without a Kept account"
+msgstr "仅作联系人记录,无 Kept 账号"
+
+msgid "A copy without the serial or purchase."
+msgstr "不含序列号或购买信息的副本。"
+
+msgid "A few uploads are already on their way. Try this one again in a moment."
+msgstr "当前有多个上传任务正在进行,请稍后再试。"
+
+msgid "A few you'd hate to lose track of: a charger, the drill, the passports."
+msgstr "几样你最不想弄丢的东西:比如充电器、电钻、护照。"
+
+msgid "a field"
+msgstr "一个字段"
+
+msgid "A field group"
+msgstr "字段组"
+
+msgid "A Kept code is 6 letters and digits, like 7KQ‑4MZ."
+msgstr "Kept 编码由 6 位字母和数字组成,例如 7KQ‑4MZ。"
+
+msgid "A key is a lower-case word in English letters, digits and _, starting with a letter."
+msgstr "键名需为以英文字母开头的小写字母、数字和下划线 _ 的组合。"
+
+msgid "A kind needs a name."
+msgstr "位置类型需要名称。"
+
+msgid "A link or a QR code; nobody needs email."
+msgstr "通过链接或二维码分享,无需对方提供邮箱。"
+
+msgid "A location always needs an owner. Transfer it first."
+msgstr "空间必须始终有所有者。请先转让所有权。"
+
+msgid "A name is needed."
+msgstr "请填写名称。"
+
+msgid "A new shop instead"
+msgstr "改用新商店"
+
+msgid "A new version is ready"
+msgstr "新版本已就绪"
+
+msgid "A number, like 52340."
+msgstr "输入数字,例如 52340。"
+
+msgid "A number, like 53100."
+msgstr "数字,例如 53100。"
+
+msgid "A number, like 5800.00."
+msgstr "数字,例如 5800.00。"
+
+msgid "A PDF of the things here, grouped by place, with their photos and short IDs. Prices are in it only where you can see them."
+msgstr "生成此处物品的 PDF 清单,按位置分组并附带照片和短 ID。仅在你拥有查看权限的范围内包含价格。"
+
+msgid "a person"
+msgstr "某位联系人"
+
+msgid "a place"
+msgstr "一个位置"
+
+msgid "A place can't keep meter readings. Remove its meters first."
+msgstr "位置无法记录表计读数。请先移除其关联的表计。"
+
+msgid "a place kind"
+msgstr "一种位置类型"
+
+msgid "A price needs a currency."
+msgstr "价格必须指定货币。"
+
+msgid "A product"
+msgstr "产品"
+
+msgid "A product barcode"
+msgstr "商品条形码"
+
+msgid "A report holds at most {max} things. Choose some places, types or tags to make it smaller."
+msgstr "单份报告最多包含 {max} 件物品。请筛选部分位置、类型或分类标签以缩小范围。"
+
+msgid "A short code for the printed label on the shelf or door"
+msgstr "用于贴在架子或门上的打印标签短码"
+
+msgid "A similar name was already here. An admin can merge them if they're the same."
+msgstr "已存在相似名称。若为同一对象,管理员可将其合并。"
+
+msgid "A similar name was already here. If they're the same, merge them."
+msgstr "已存在相似名称。如果指向同一对象,请将它们合并。"
+
+msgid "a tag"
+msgstr "分类标签"
+
+msgid "a thing"
+msgstr "一件物品"
+
+msgid "A thing needs a name."
+msgstr "物品必须填写名称。"
+
+msgid "A to Z"
+msgstr "按字母 A 到 Z"
+
+msgid "a type"
+msgstr "某个类型"
+
+msgid "A type can't sit inside itself or a type below it. Pick a parent outside this branch."
+msgstr "类型不能置于自身或其子类型之下。请选择此分支之外的父级类型。"
+
+msgid "A type inherits the capabilities and fields of the types it sits inside."
+msgstr "子类型会继承其所属上级类型的功能与字段。"
+
+msgid "A type needs a name."
+msgstr "类型需要填写名称。"
+
+msgid "A type sets the icon, capabilities and fields of the things that use it, and the types inside it inherit them. Built-in types come ready; customise one, or make your own."
+msgstr "「类型」决定了使用它的物品的图标、能力与字段,子类型会继承父类型的设置。内置类型已为你配好;你可以自定义修改,也可以新建自己的类型。"
+
+msgid "a vendor"
+msgstr "商家"
+
+msgid "Accept"
+msgstr "接受"
+
+msgid "Accept {0} names"
+msgstr "采纳 {0} 处命名"
+
+msgid "Accept names"
+msgstr "采纳名称"
+
+msgid "Accept the receipt"
+msgstr "采纳该收据"
+
+msgid "Accept the selected names"
+msgstr "采纳所选名称"
+
+msgid "Accepted {display}"
+msgstr "已采纳 {display}"
+
+msgid "Accepted {n} names"
+msgstr "已采纳 {n} 个名称"
+
+msgid "Accepted the receipt"
+msgstr "已确认收据"
+
+msgid "Access"
+msgstr "访问权限"
+
+msgid "Accessory of"
+msgstr "属于以下物品的配件"
+
+msgid "Account"
+msgstr "账号"
+
+msgid "Account settings · Types"
+msgstr "账号设置 · 类型"
+
+msgid "Account-wide"
+msgstr "账号全局"
+
+msgid "Acquired from"
+msgstr "购自 / 获自"
+
+msgid "Actions"
+msgstr "操作"
+
+msgid "Actions for {name}"
+msgstr "{name} 的操作"
+
+msgid "Active {active} · signed in {since}"
+msgstr "最近活跃 {active} · 登录于 {since}"
+
+msgid "Active {when}"
+msgstr "启用时间:{when}"
+
+msgid "Activity"
+msgstr "动态"
+
+msgid "Add"
+msgstr "添加"
+
+msgid "Add 3 things"
+msgstr "添加 3 件物品"
+
+msgid "Add a box to {hereName}"
+msgstr "向 {hereName} 添加收纳箱"
+
+msgid "Add a brand"
+msgstr "添加品牌"
+
+msgid "Add a field"
+msgstr "添加字段"
+
+msgid "Add a file"
+msgstr "添加文件"
+
+msgid "Add a group"
+msgstr "添加分组"
+
+msgid "Add a person"
+msgstr "添加成员"
+
+msgid "Add a photo"
+msgstr "添加照片"
+
+msgid "Add a room or spot to {hereName}"
+msgstr "向 {hereName} 添加房间或点位"
+
+msgid "Add a shop or service"
+msgstr "添加商店或服务商"
+
+msgid "Add a tag"
+msgstr "添加分类标签"
+
+msgid "Add a thing"
+msgstr "添加物品"
+
+msgid "Add a thing to {hereName}"
+msgstr "向 {hereName} 添加物品"
+
+msgid "Add as"
+msgstr "添加为"
+
+msgid "Add as a new thing"
+msgstr "添加为新物品"
+
+msgid "Add here"
+msgstr "添加到此处"
+
+msgid "Add photos from your files with Gallery in Capture."
+msgstr "在「采集」中通过相册从文件添加照片。"
+
+msgid "Add room or spot"
+msgstr "添加房间或点位"
+
+msgid "Add someone without email"
+msgstr "添加无邮箱成员"
+
+msgid "Add the first photo"
+msgstr "添加第一张照片"
+
+msgid "Add the people things belong to, and who you lend to."
+msgstr "添加物品所属的物主,以及你常借给的联系人。"
+
+msgid "Add the rooms and spots you'll put things in. Change them any time."
+msgstr "添加存放物品的房间和点位,之后可随时修改。"
+
+msgid "Add what's inside, so you can find it without opening it."
+msgstr "添加箱内物品清单,无需开箱即可查找。"
+
+msgid "Added {0}"
+msgstr "已添加 {0}"
+
+msgid "Added {added}"
+msgstr "已添加 {added}"
+
+msgid "Added {name}"
+msgstr "已添加 {name}"
+
+msgid "Added {typed}"
+msgstr "已添加 {typed}"
+
+msgid "Added {value}"
+msgstr "已添加 {value}"
+
+msgid "Added <0>{0}0>. Is it <1>{1}1>, already here?"
+msgstr "已添加 <0>{0}0>。它是否就是这里已有的 <1>{1}1>?"
+
+msgid "Added 3 things"
+msgstr "已添加 3 件物品"
+
+msgid "Added a new thing"
+msgstr "添加了新物品"
+
+msgid "Added to your shops when you accept."
+msgstr "采纳后将添加到你的商店列表。"
+
+msgid "Address"
+msgstr "地址"
+
+msgid "Adds fuel, things you run out of, passwords and codes, moving house, and \"Connect ChatGPT or Claude\"."
+msgstr "开启加油/充电、消耗品、密码与编码、搬家打包,以及「连接 ChatGPT 或 Claude」。"
+
+msgid "Adds receipts and warranties, reminders, lending, paperwork and vehicles."
+msgstr "新增收据与保修、提醒、借出记录、单据文书及车辆管理功能。"
+
+msgid "Admin"
+msgstr "管理员"
+
+msgctxt "settings section"
+msgid "Admin"
+msgstr "管理员"
+
+msgid "admin in {n}"
+msgstr "在 {n} 个空间担任管理员"
+
+msgid "Admins"
+msgstr "管理员"
+
+msgctxt "instance admins tab"
+msgid "Admins"
+msgstr "管理员"
+
+msgid "Admins manage members, viewers and settings. Only the owner changes admins."
+msgstr "管理员可管理成员、查看者和空间设置。只有所有者可以任免管理员。"
+
+msgid "After this, signing in asks for a 6-digit code from an authenticator app (1Password, Google Authenticator, Aegis…) as well as your password or sign-in link."
+msgstr "启用后,登录时除了密码或登录链接外,还需输入验证器应用(如 1Password、Google Authenticator、Aegis 等)生成的 6 位验证码。"
+
+msgid "AI"
+msgstr "AI"
+
+msgctxt "history kind"
+msgid "AI"
+msgstr "AI"
+
+msgid "AI and barcode lookup can be connected later, from Settings. Kept works without them."
+msgstr "AI 和条形码查询可稍后在「设置」中连接,没有它们 Kept 也能正常使用。"
+
+msgid "AI assistant"
+msgstr "AI 助手"
+
+msgid "AI capture"
+msgstr "AI 采集"
+
+msgid "AI capture and the assistant"
+msgstr "AI 拍照识别与助手"
+
+msgid "AI capture and the assistant come on in any preset once an AI provider is connected."
+msgstr "连接 AI 服务商后,任何预设方案下都会开启 AI 拍照识别与助手。"
+
+msgid "AI in this location"
+msgstr "此空间中的 AI"
+
+msgid "AI is paused"
+msgstr "AI 已暂停"
+
+msgid "AI isn't working here · ask {0}"
+msgstr "此处 AI 暂不可用 · 请询问 {0}"
+
+msgid "AI isn't working here · ask an admin"
+msgstr "AI 当前不可用 · 请联系管理员"
+
+msgid "AI paused"
+msgstr "AI 已暂停"
+
+msgid "AI paused until {when}"
+msgstr "AI 已暂停,直至 {when}"
+
+msgid "AI settings"
+msgstr "AI 设置"
+
+msgid "AI usage"
+msgstr "AI 用量"
+
+msgid "Alerts"
+msgstr "告警"
+
+msgid "Aliases for imported things"
+msgstr "导入物品的别名"
+
+msgid "All"
+msgstr "全部"
+
+msgid "All activity"
+msgstr "全部动态"
+
+msgid "All filters"
+msgstr "全部筛选"
+
+msgid "All place kinds"
+msgstr "所有位置类型"
+
+msgid "All places"
+msgstr "所有位置"
+
+msgid "All reviewed"
+msgstr "已全部复核"
+
+msgid "All types"
+msgstr "全部类型"
+
+msgid "Already claimed"
+msgstr "已被认领"
+
+msgid "Already in Kept"
+msgstr "已在 Kept 中"
+
+msgid "Also called"
+msgstr "别名"
+
+msgid "Always on: one of the five defaults"
+msgstr "始终开启:五个默认选项之一"
+
+msgid "Always there, for things that don't have a place yet"
+msgstr "始终存在,用于存放尚未确定位置的物品"
+
+msgid "An invite link works once, for 7 days. Unused ones show here."
+msgstr "每个邀请链接仅限使用一次,有效期 7 天。未使用的链接显示在这里。"
+
+msgid "Android"
+msgstr "Android"
+
+msgid "Android: tap the icon beside the address, then Permissions › Camera › Allow."
+msgstr "Android:轻点地址栏旁的图标,然后依次进入“权限 › 相机 › 允许”。"
+
+msgid "Another app is using the camera. Close it, then come back."
+msgstr "其他应用正在占用相机。请先关闭该应用,然后再回来重试。"
+
+msgid "Another place"
+msgstr "其他位置"
+
+msgid "Answering"
+msgstr "正在回答"
+
+msgid "Anyone with the address can create an account"
+msgstr "任何能访问此地址的人都可以创建账号"
+
+msgid "Apartment"
+msgstr "公寓"
+
+msgid "Apply"
+msgstr "应用"
+
+msgid "Archive"
+msgstr "归档"
+
+msgid "Archive {0}"
+msgstr "归档 {0}"
+
+msgid "Archive or delete this home."
+msgstr "归档或删除此空间。"
+
+msgid "Archived fields"
+msgstr "已归档字段"
+
+msgid "Archived fields · {0}"
+msgstr "已归档字段 · {0}"
+
+msgid "Archived fields · values are kept"
+msgstr "已归档字段 · 已有数值会保留"
+
+msgid "As a room or spot it can't keep its {lost}. They are removed; its history stays."
+msgstr "作为房间或点位时,无法保留其{lost}。这些内容将被移除,但其历史记录会保留。"
+
+msgid "As of last sync, {asOf}"
+msgstr "截至上次同步:{asOf}"
+
+msgid "Ask <0>{manager}0> to resume"
+msgstr "请联系 <0>{manager}0> 恢复"
+
+msgid "Ask an admin"
+msgstr "联系管理员"
+
+msgid "Ask an admin of {name} if something here should change."
+msgstr "如果此处需要修改,请联系 {name} 的管理员。"
+
+msgid "Ask an admin of this location to turn it on."
+msgstr "请联系此空间的管理员开启该功能。"
+
+msgid "Ask the assistant"
+msgstr "询问助手"
+
+msgid "Ask your instance admin to download the recovery kit first."
+msgstr "请先让实例管理员下载恢复工具包。"
+
+msgid "Asked for on new edits only; things saved before aren't flagged."
+msgstr "仅对新增编辑要求验证;之前保存的物品不会被标记。"
+
+msgid "Asset {0}"
+msgstr "资产 {0}"
+
+msgid "Assistant"
+msgstr "AI 助手"
+
+msgid "At least 12 characters."
+msgstr "至少 12 个字符。"
+
+msgid "At least 8 characters."
+msgstr "至少 8 个字符。"
+
+msgid "At least 8 characters. A few unrelated words is easy to remember."
+msgstr "至少 8 个字符。几个不相关的词组合起来既安全又好记。"
+
+msgid "At most {max} characters."
+msgstr "最多 {max} 个字符。"
+
+msgid "At most 200 characters."
+msgstr "最多 200 个字符。"
+
+msgid "Attach to an existing thing"
+msgstr "关联到现有物品"
+
+msgid "Attached a file to {name}"
+msgstr "已为 {name} 添加附件"
+
+msgid "Attachments"
+msgstr "附件"
+
+msgid "Back"
+msgstr "返回"
+
+msgid "Back in use"
+msgstr "恢复使用"
+
+msgid "Back to editing"
+msgstr "返回编辑"
+
+msgid "Back to Home"
+msgstr "返回首页"
+
+msgid "Back to sign in"
+msgstr "返回登录"
+
+msgid "Background work is keeping up. A job that fails every retry shows up here."
+msgstr "后台任务运行正常。经过所有重试仍失败的任务会显示在这里。"
+
+msgid "Backup code"
+msgstr "备用恢复码"
+
+msgid "Balcony"
+msgstr "阳台"
+
+msgid "Barcode"
+msgstr "条形码"
+
+msgid "Barcode scanner"
+msgstr "扫码枪"
+
+msgid "Batch undone"
+msgstr "已撤销批量操作"
+
+msgid "Bathroom"
+msgstr "卫生间"
+
+msgid "Bedroom"
+msgstr "卧室"
+
+msgid "Belongs to"
+msgstr "属于"
+
+msgid "Belongs to {name}"
+msgstr "属于 {name}"
+
+msgid "Best match first"
+msgstr "最佳匹配优先"
+
+msgid "Between 1 and {0}."
+msgstr "请输入 1 到 {0} 之间的数字。"
+
+msgid "Blank label"
+msgstr "空白标签"
+
+msgid "Bought"
+msgstr "已购入"
+
+msgid "Bought from {name}"
+msgstr "购自 {name}"
+
+msgid "Bought on"
+msgstr "购买日期"
+
+msgid "Box / container"
+msgstr "箱子 / 收纳盒"
+
+msgid "Box 3"
+msgstr "3 号箱"
+
+msgid "Box check"
+msgstr "箱内核对"
+
+msgid "Box check · in progress"
+msgstr "箱内清点 · 进行中"
+
+msgid "Box check done"
+msgstr "开箱清点完成"
+
+msgid "Box inside · not opened"
+msgstr "内有箱子 · 尚未打开"
+
+msgid "Boxes"
+msgstr "收纳箱"
+
+msgid "brand"
+msgstr "品牌"
+
+msgid "Brand"
+msgstr "品牌"
+
+msgid "Brand added"
+msgstr "已添加品牌"
+
+msgid "brand and model match"
+msgstr "品牌与型号匹配"
+
+msgid "Brand changed"
+msgstr "已更改品牌"
+
+msgid "Brand deleted"
+msgstr "品牌已删除"
+
+msgid "Brand merged"
+msgstr "品牌已合并"
+
+msgid "Brands"
+msgstr "品牌"
+
+msgid "Brands are added here, or while you add a thing."
+msgstr "可以在此处添加品牌,也可以在添加物品时顺便添加。"
+
+msgid "Bring it back"
+msgstr "放回原处"
+
+msgid "British pound"
+msgstr "英镑"
+
+msgid "Broken"
+msgstr "已损坏"
+
+msgid "Browsers only allow the camera, installing the app, push notifications and location on a secure address. Two ways to get one:"
+msgstr "浏览器仅允许在安全地址上使用摄像头、安装应用、接收推送通知以及获取定位。获取安全地址的两种方法:"
+
+msgid "Built in"
+msgstr "内置"
+
+msgid "Built in · Customise it to rename it or give it fields"
+msgstr "内置 · 可自定义以重命名或添加字段"
+
+msgid "Built in · read-only · its fields are listed above"
+msgstr "内置 · 只读 · 字段已列于上方"
+
+msgid "Built in · read-only until you customise it"
+msgstr "内置 · 自定义前为只读"
+
+msgid "Built-in field group · read-only"
+msgstr "内置字段组 · 只读"
+
+msgid "Built-in types are customised first: use Customise to make an editable copy."
+msgstr "内置类型需先自定义副本后才能编辑:请点击“自定义”创建可编辑副本。"
+
+msgid "Built-in types are shared by everyone on this server. Customise makes your account's own copy: your things of this type move to it, the built-in types below it come along, and then you can change its name, icon, capabilities and fields."
+msgstr "内置类型由本服务器所有用户共享。点击「自定义」会为你的账号创建专属副本:属于该类型的物品会迁移过去,其下方的内置子类型也会一并复制,之后你就可以修改它的名称、图标、功能与字段。"
+
+msgid "Bundled with"
+msgstr "捆绑于"
+
+msgid "Buttons"
+msgstr "按钮"
+
+msgid "By {by} · link expires {expires}"
+msgstr "由 {by} 创建 · 链接将于 {expires} 过期"
+
+msgid "by {groupName}"
+msgstr "由 {groupName}"
+
+msgid "by kind"
+msgstr "按位置类型"
+
+msgid "by type"
+msgstr "按类型"
+
+msgid "Cables"
+msgstr "线缆"
+
+msgid "Came from"
+msgstr "来源位置"
+
+msgid "Camera"
+msgstr "相机"
+
+msgctxt "map shape"
+msgid "Camera"
+msgstr "相机"
+
+msgid "Camera access is off for Kept."
+msgstr "Kept 的相机权限未开启。"
+
+msgid "Camera view"
+msgstr "相机视图"
+
+msgid "Camera, offline capture and install need HTTPS."
+msgstr "相机、离线录入与应用安装均需使用 HTTPS。"
+
+msgid "Camping box"
+msgstr "露营箱"
+
+msgid "Can carry warranties."
+msgstr "可关联保修信息。"
+
+msgid "Can hold other things, like a box or a car."
+msgstr "可容纳其他物品,例如箱子或车辆。"
+
+msgid "Can hold several values"
+msgstr "可填写多个值"
+
+msgid "Can't scan it?"
+msgstr "无法扫码?"
+
+msgid "Can't undo: {who} changed {field} since"
+msgstr "无法撤销:{who} 在此之后修改了 {field}"
+
+msgid "Can't undo: {who} changed it since"
+msgstr "无法撤销:{who} 此后已对其做了修改"
+
+msgid "Can't undo: it changed since"
+msgstr "无法撤销:此后内容已发生变更"
+
+msgid "Can't undo: it's more than 7 days old"
+msgstr "无法撤销:已超过 7 天"
+
+msgid "Canadian dollar"
+msgstr "加元"
+
+msgid "Cancel"
+msgstr "取消"
+
+msgid "Capabilities"
+msgstr "功能特性"
+
+msgid "Capture"
+msgstr "录入"
+
+msgid "Capture done"
+msgstr "采集完成"
+
+msgid "Capture into"
+msgstr "采集至"
+
+msgid "Capture into {name}"
+msgstr "快速录入至 {name}"
+
+msgid "Capture mode"
+msgstr "采集模式"
+
+msgid "Captured into <0>{locationName}0>, no place yet"
+msgstr "已录入 <0>{locationName}0>,暂未指定位置"
+
+msgid "Captured."
+msgstr "已采集。"
+
+msgid "Captures from another account are on this phone"
+msgstr "此手机上存有其他账号的采集记录"
+
+msgid "Captures that haven't synced are deleted from this phone. Synced drafts from this batch go to the trash."
+msgstr "未同步的采集记录将从此手机中删除。此批次中已同步的草稿将移入回收站。"
+
+msgid "Capturing into {path}. Change place"
+msgstr "正在采集到 {path}。更改位置"
+
+msgid "Cards and tabs"
+msgstr "卡片与标签页"
+
+msgid "carousel"
+msgstr "轮播图"
+
+msgid "Centered"
+msgstr "居中"
+
+msgid "Change"
+msgstr "更改"
+
+msgid "Change email"
+msgstr "更改邮箱"
+
+msgid "Change icon"
+msgstr "更改图标"
+
+msgid "Change lifecycle"
+msgstr "更改生命周期状态"
+
+msgid "Change lifecycle…"
+msgstr "更改生命周期…"
+
+msgid "Change photo"
+msgstr "更换照片"
+
+msgid "Change the name or the kind of place"
+msgstr "更改名称或位置类型"
+
+msgid "Change the type"
+msgstr "更改类型"
+
+msgid "Change type"
+msgstr "更改类型"
+
+msgid "Change your email"
+msgstr "更改邮箱"
+
+msgid "Changed"
+msgstr "已变更"
+
+msgid "changed · value not recorded"
+msgstr "已更改 · 未记录具体数值"
+
+msgid "Changed a file on {name}"
+msgstr "修改了 {name} 上的文件"
+
+msgid "Changed since you opened it"
+msgstr "自你打开后已有变更"
+
+msgid "Changed the status of {name}"
+msgstr "已更改 {name} 的状态"
+
+msgid "Changed the type of {name}"
+msgstr "已更改 {name} 的类型"
+
+msgid "Changes to this place show here, newest first."
+msgstr "此位置的变更记录会按最新优先显示在这里。"
+
+msgid "Changes to this thing show here, newest first."
+msgstr "此物品的更改记录显示在这里,按最新优先排列。"
+
+msgid "Check now"
+msgstr "立即检查"
+
+msgid "Check the camera, offline support and storage, and copy a report."
+msgstr "检查摄像头、离线支持与存储状态,并复制诊断报告。"
+
+msgid "Check this device"
+msgstr "检查此设备"
+
+msgid "Check your email"
+msgstr "请查收你的邮箱"
+
+msgid "Checks what this phone or browser can do: the camera, offline support, storage and install. Nothing is sent; you copy the report yourself. The camera check asks for permission."
+msgstr "检测此手机或浏览器的支持情况:相机、离线能力、存储空间与安装支持。不会自动上传任何信息,报告由你自行复制。相机检测会请求授权。"
+
+msgid "Choices"
+msgstr "选项"
+
+msgid "Choose a date"
+msgstr "选择日期"
+
+msgid "Choose a new password"
+msgstr "设置新密码"
+
+msgid "Choose a place"
+msgstr "选择位置"
+
+msgid "Choose an icon"
+msgstr "选择图标"
+
+msgid "Choose an item to review it here."
+msgstr "选择一项在此处审核。"
+
+msgid "Choose another place"
+msgstr "选择其他位置"
+
+msgid "Choose one of your shops"
+msgstr "选择一个你常用的商店"
+
+msgid "Choose photos"
+msgstr "选择照片"
+
+msgid "Choose the currency."
+msgstr "选择币种。"
+
+msgid "Choose the date on the receipt."
+msgstr "选择收据上的日期。"
+
+msgid "Choose the last day."
+msgstr "选择结束日期。"
+
+msgid "Choose the shop."
+msgstr "请选择商店。"
+
+msgid "Choose the thing each linked line is."
+msgstr "选择每条已关联项目对应的物品。"
+
+msgid "Choose what happens to what's inside"
+msgstr "选择如何处理其中的物品"
+
+msgid "Choose where it is."
+msgstr "选择它所在的位置。"
+
+msgid "Claim"
+msgstr "理赔"
+
+msgid "Claim it"
+msgstr "认领"
+
+msgid "Claim this label"
+msgstr "认领此标签"
+
+msgid "Clear"
+msgstr "清除"
+
+msgid "Clear all"
+msgstr "全部清除"
+
+msgid "Clear recent searches"
+msgstr "清除最近搜索"
+
+msgid "Clear search"
+msgstr "清除搜索"
+
+msgid "Clear selection"
+msgstr "清除选择"
+
+msgid "close"
+msgstr "关闭"
+
+msgid "Close"
+msgstr "关闭"
+
+msgid "Close box check"
+msgstr "结束箱内核对"
+
+msgid "Close scanner"
+msgstr "关闭扫码器"
+
+msgid "Closed. People join through an invite, or you add a managed account."
+msgstr "已关闭注册。成员需通过邀请加入,或由你添加托管账号。"
+
+msgid "Closet"
+msgstr "衣柜间"
+
+msgid "Code on the label"
+msgstr "标签上的编码"
+
+msgid "Collapse sidebar"
+msgstr "收起侧边栏"
+
+msgid "colour"
+msgstr "颜色"
+
+msgid "Colour"
+msgstr "颜色"
+
+msgid "Colour tokens"
+msgstr "色彩令牌"
+
+msgid "Coming soon"
+msgstr "即将推出"
+
+msgid "Compares your position with your locations on this phone. It is never sent or kept."
+msgstr "仅在此手机本地将你的位置与各空间位置进行比对,绝不会发送或保留你的定位信息。"
+
+msgid "Complete"
+msgstr "完成"
+
+msgctxt "schedule action"
+msgid "Complete"
+msgstr "完成"
+
+msgid "Computer"
+msgstr "电脑"
+
+msgid "Condition"
+msgstr "成色"
+
+msgid "Condition when lent"
+msgstr "借出时状况"
+
+msgid "Condition when returned"
+msgstr "归还时成色"
+
+msgid "Confirm"
+msgstr "确认"
+
+msgid "Confirm it's you"
+msgstr "验证你的身份"
+
+msgid "Confirm it's you. Signed in with a passkey only? Sign out and back in, then change your email within 10 minutes."
+msgstr "请验证身份。如果是仅通过通行密钥登录的,请先退出再重新登录,并在 10 分钟内更改邮箱。"
+
+msgid "Confirm or reject each suggested value first (Y or N)."
+msgstr "请先确认或拒绝每一项建议值(是或否)。"
+
+msgid "Confirm or reject each suggested value first."
+msgstr "请先确认或拒绝每一项建议值。"
+
+msgid "Confirm the email change"
+msgstr "确认更改邮箱"
+
+msgid "Confirm the suggested value"
+msgstr "确认建议值"
+
+msgid "Confirm your email address first"
+msgstr "请先验证你的电子邮箱"
+
+msgid "Confirm your second factor to continue."
+msgstr "请完成双重验证以继续。"
+
+msgid "Confirmed"
+msgstr "已确认"
+
+msgid "Connect an AI provider"
+msgstr "连接 AI 服务商"
+
+msgid "Connect ChatGPT or Claude"
+msgstr "连接 ChatGPT 或 Claude"
+
+msgid "Connected AI"
+msgstr "已连接的 AI"
+
+msgid "Consumable"
+msgstr "消耗品"
+
+msgid "Contact"
+msgstr "联系人"
+
+msgid "Contact details changed"
+msgstr "联系方式已更改"
+
+msgid "Contact for {name}"
+msgstr "{name} 的联系邮箱"
+
+msgid "Contact saved"
+msgstr "联系人已保存"
+
+msgid "Container"
+msgstr "容器"
+
+msgid "Content width"
+msgstr "内容宽度"
+
+msgid "Contents"
+msgstr "内部物品"
+
+msgid "Contents of {name}"
+msgstr "{name} 内的物品"
+
+msgid "Continue"
+msgstr "继续"
+
+msgid "Convert"
+msgstr "转换"
+
+msgid "Convert and lose these?"
+msgstr "确认转换并丢弃这些内容吗?"
+
+msgid "Convert anyway"
+msgstr "仍要转换"
+
+msgid "Convert to a room or spot"
+msgstr "转换为房间或点位"
+
+msgid "Copied"
+msgstr "已复制"
+
+msgid "Copied · logged"
+msgstr "已复制 · 已记录"
+
+msgid "Copy"
+msgstr "复制"
+
+msgid "Copy all codes"
+msgstr "复制所有恢复码"
+
+msgid "Copy code"
+msgstr "复制代码"
+
+msgid "Copy key"
+msgstr "复制密钥"
+
+msgid "Copy link"
+msgstr "复制链接"
+
+msgid "Copy report"
+msgstr "复制报告"
+
+msgid "Copy the address from the address bar."
+msgstr "从浏览器地址栏复制地址。"
+
+msgid "Copy the code"
+msgstr "复制验证码"
+
+msgid "Cordless drill"
+msgstr "无绳电钻"
+
+msgid "Cordless drill with two batteries and the long charger"
+msgstr "带两块电池和长款充电器的无绳电钻"
+
+msgid "cost unknown"
+msgstr "费用未知"
+
+msgid "Couldn't add it"
+msgstr "无法添加"
+
+msgid "Couldn't change it"
+msgstr "无法更改"
+
+msgid "Couldn't change the reading"
+msgstr "无法修改读数"
+
+msgid "Couldn't change the type"
+msgstr "无法更改类型"
+
+msgid "Couldn't check on the PDF"
+msgstr "无法检查 PDF 状态"
+
+msgid "Couldn't copy"
+msgstr "无法复制"
+
+msgid "Couldn't finish the check"
+msgstr "无法完成清点"
+
+msgid "Couldn't link them"
+msgstr "无法关联它们"
+
+msgid "Couldn't load the choices. Try again in a moment."
+msgstr "无法加载选项,请稍后再试。"
+
+msgid "Couldn't load this"
+msgstr "无法加载此内容"
+
+msgid "Couldn't look that up. Try again."
+msgstr "未能查到,请重试。"
+
+msgid "Read {shown} from the printed code"
+msgstr "从印制的编码中读取了 {shown}"
+
+msgid "Couldn't make the PDF"
+msgstr "无法生成 PDF"
+
+msgid "Couldn't move it"
+msgstr "无法移动"
+
+msgid "Couldn't move them. Try again."
+msgstr "无法移动,请重试。"
+
+msgid "Couldn't open it"
+msgstr "无法打开"
+
+msgid "Couldn't open this invite"
+msgstr "无法打开此邀请"
+
+msgid "Couldn't read the photo"
+msgstr "无法读取该照片"
+
+msgid "Couldn't read this photo (provider error)"
+msgstr "无法识别此照片(服务商出错)"
+
+msgid "Couldn't read this photo (the answer made no sense)"
+msgstr "无法识别此照片(返回结果无法解析)"
+
+msgid "Couldn't read this photo (the answer was cut off)"
+msgstr "无法识别此照片(返回结果被截断)"
+
+msgid "Couldn't read this photo (the provider refused it)"
+msgstr "无法识别此照片(服务商拒绝处理)"
+
+msgid "Couldn't read this photo (the provider took too long)"
+msgstr "无法读取此照片(服务商响应超时)"
+
+msgid "Couldn't remove it"
+msgstr "无法移除"
+
+msgid "Couldn't remove the link"
+msgstr "无法移除链接"
+
+msgid "Couldn't reveal {label}"
+msgstr "无法显示 {label}"
+
+msgid "Couldn't save"
+msgstr "无法保存"
+
+msgid "Couldn't save {label}"
+msgstr "无法保存 {label}"
+
+msgid "Couldn't save that capture"
+msgstr "无法保存该录入内容"
+
+msgid "Couldn't sync"
+msgstr "无法同步"
+
+msgid "Couldn't trash it"
+msgstr "无法移入回收站"
+
+msgid "Couldn't undo that"
+msgstr "无法撤销该操作"
+
+msgid "Couldn't undo the synced ones"
+msgstr "无法撤销已同步的项目"
+
+msgid "Couldn't upload {0}"
+msgstr "无法上传 {0}"
+
+msgid "Create"
+msgstr "创建"
+
+msgid "Create {displayName}"
+msgstr "创建{displayName}"
+
+msgid "Create a new thing from this line"
+msgstr "从此行创建新物品"
+
+msgid "Create account"
+msgstr "创建账号"
+
+msgid "Create account and join"
+msgstr "创建账号并加入"
+
+msgid "Create an account and join"
+msgstr "创建账号并加入"
+
+msgid "Create invite link"
+msgstr "创建邀请链接"
+
+msgid "Create the first account"
+msgstr "创建第一个账户"
+
+msgid "Create your first home"
+msgstr "创建你的第一个家"
+
+msgid "Created {created}"
+msgstr "创建于 {created}"
+
+msgid "Created a home"
+msgstr "已创建一个家庭空间"
+
+msgid "Currencies"
+msgstr "货币"
+
+msgid "Currencies people can pick for locations and prices. The five defaults, and any currency a location uses, stay on."
+msgstr "用户可为空间和价格选择的货币。五种默认货币以及任一空间正在使用的货币会保持开启。"
+
+msgid "currency"
+msgstr "币种"
+
+msgid "Currency"
+msgstr "货币"
+
+msgid "Custom range"
+msgstr "自定义范围"
+
+msgid "Customise"
+msgstr "自定义"
+
+msgid "Customise makes this account's own copy: every place of this kind uses it, and you can rename it and give it fields."
+msgstr "自定义会创建此账号专属的副本:所有该类型的空间位置都将使用它,你可以重命名并为其添加字段。"
+
+msgid "Customised from the built-in type"
+msgstr "基于内置类型自定义"
+
+msgid "Danger zone"
+msgstr "危险操作区"
+
+msgid "Dark"
+msgstr "深色"
+
+msgid "Database"
+msgstr "数据库"
+
+msgid "Date"
+msgstr "日期"
+
+msgid "Date on the receipt"
+msgstr "收据上的日期"
+
+msgid "Default"
+msgstr "默认"
+
+msgid "Default warranty (months)"
+msgstr "默认保修期(月)"
+
+msgid "Delete"
+msgstr "删除"
+
+msgid "Delete {0}"
+msgstr "删除 {0}"
+
+msgid "Delete {name}"
+msgstr "删除 {name}"
+
+msgid "Delete {name} for good?"
+msgstr "永久删除 {name}?"
+
+msgid "Delete {name} permanently"
+msgstr "永久删除 {name}"
+
+msgid "Delete {name}?"
+msgstr "删除 {name}?"
+
+msgid "Delete permanently"
+msgstr "永久删除"
+
+msgid "Delete the saved search {name}?"
+msgstr "删除已保存的搜索“{name}”?"
+
+msgid "Delete the saved view {name}?"
+msgstr "要删除已保存的视图「{name}」吗?"
+
+msgid "Delete them"
+msgstr "删除它们"
+
+msgid "Deleted {0}"
+msgstr "已删除 {0}"
+
+msgid "Deleted {deletedOn} · gone for good on {purgeOn}"
+msgstr "删除于 {deletedOn} · 将于 {purgeOn} 彻底清除"
+
+msgid "Deleted {name}"
+msgstr "已删除 {name}"
+
+msgid "Deleted {name} for good"
+msgstr "已永久删除 {name}"
+
+msgid "Deleted by"
+msgstr "删除者"
+
+msgid "Description"
+msgstr "描述"
+
+msgid "Design system"
+msgstr "设计系统"
+
+msgid "Destroyed"
+msgstr "已损毁"
+
+msgid "Details"
+msgstr "详情"
+
+msgid "Device"
+msgstr "设备"
+
+msgid "Diagnostics"
+msgstr "诊断信息"
+
+msgid "Diagnostics results"
+msgstr "诊断结果"
+
+msgid "Dialog, confirm and toast"
+msgstr "弹窗、确认框与轻提示"
+
+msgid "Did you mean"
+msgstr "你是不是想找"
+
+msgid "Digits in Arabic"
+msgstr "阿拉伯数字"
+
+msgid "Disable"
+msgstr "停用"
+
+msgid "Disable {who}?"
+msgstr "停用 {who}?"
+
+msgid "Disabled"
+msgstr "已停用"
+
+msgid "Discard"
+msgstr "丢弃"
+
+msgid "Discard {count} drafts?"
+msgstr "舍弃 {count} 份草稿?"
+
+msgid "Discard {display}?"
+msgstr "放弃 {display}?"
+
+msgid "Discard or dismiss"
+msgstr "丢弃或忽略"
+
+msgid "Discard this job?"
+msgstr "要丢弃此任务吗?"
+
+msgid "Discard this reading?"
+msgstr "丢弃此读数?"
+
+msgid "Discarded"
+msgstr "已放弃"
+
+msgid "Discarded {display}"
+msgstr "已舍弃 {display}"
+
+msgid "Discarded {x} drafts"
+msgstr "已放弃 {x} 份草稿"
+
+msgid "Discarded the reading"
+msgstr "已放弃该读数"
+
+msgid "Dismiss"
+msgstr "忽略"
+
+msgid "Dismissed"
+msgstr "已忽略"
+
+msgid "Display"
+msgstr "显示"
+
+msgid "Display options"
+msgstr "显示选项"
+
+msgid "Display options: sorted by {sortName}, {dirName}"
+msgstr "显示选项:按{sortName}排序,{dirName}"
+
+msgid "Disposed of"
+msgstr "已报废处理"
+
+msgid "Document"
+msgstr "文档"
+
+msgid "Doesn't work"
+msgstr "无法正常使用"
+
+msgid "Done"
+msgstr "完成"
+
+msgctxt "schedule state"
+msgid "Done"
+msgstr "完成"
+
+msgid "Done. {who} gets an email about it."
+msgstr "已完成。{who} 会收到相关邮件通知。"
+
+msgid "Download"
+msgstr "下载"
+
+msgid "Draft"
+msgstr "草稿"
+
+msgid "Drafts"
+msgstr "草稿"
+
+msgid "Drafts without a name, or with values to confirm, are left for you to review."
+msgstr "没有名称或仍有数值待确认的草稿会保留在此供你核对。"
+
+msgid "Duplicate"
+msgstr "重复"
+
+msgid "Duplicated"
+msgstr "已复制"
+
+msgid "Duplicated {name}"
+msgstr "已复制 {name}"
+
+msgid "Duplicates"
+msgstr "重复项"
+
+msgid "e.g. Cordless drill"
+msgstr "例如:无绳电钻"
+
+msgid "e.g. Home"
+msgstr "例如:家里"
+
+msgid "Each one is saved and findable on this phone now. AI fills in details after sync; anything that needs you lands in the Inbox."
+msgstr "每件物品现已保存并可在此手机上检索。同步后 AI 会自动补全详细信息;需要你确认的内容会进入收件箱。"
+
+msgid "Each one is saved and findable on this phone now. Unnamed ones wait in the Inbox for a name."
+msgstr "每条记录均已保存,现可在此手机上搜索。未命名的记录将在收件箱中等待命名。"
+
+msgid "Each owner's locations share one set of types and lists."
+msgstr "同一拥有者的空间共享同一套类型与列表。"
+
+msgid "Edit"
+msgstr "编辑"
+
+msgid "Edit {0}"
+msgstr "编辑 {0}"
+
+msgid "Edit {name}"
+msgstr "编辑 {name}"
+
+msgid "Edit on {0}"
+msgstr "在 {0} 上编辑"
+
+msgid "Edit the reading"
+msgstr "编辑读数"
+
+msgid "Edited {name}"
+msgstr "已编辑 {name}"
+
+msgid "Egyptian pound"
+msgstr "埃及镑"
+
+msgid "Email"
+msgstr "电子邮箱"
+
+msgid "Email me a sign-in link"
+msgstr "通过邮件发送登录链接"
+
+msgid "Email me when something is due"
+msgstr "有到期事项时给我发邮件"
+
+msgid "Email or username"
+msgstr "邮箱或用户名"
+
+msgid "Email-change links work once, for an hour. <0>Start again from Settings0>."
+msgstr "邮箱变更链接仅限一小时内使用一次。<0>请从设置重新开始0>。"
+
+msgid "empty"
+msgstr "空"
+
+msgid "Empty"
+msgstr "空"
+
+msgid "Enable"
+msgstr "启用"
+
+msgid "Enable {who}?"
+msgstr "启用 {who}?"
+
+msgid "end details"
+msgstr "结束详情"
+
+msgid "Ended"
+msgstr "已结束"
+
+msgid "Ended on"
+msgstr "结束于"
+
+msgid "Ended with"
+msgstr "结束于"
+
+msgid "Enter a backup code."
+msgstr "输入备用恢复码。"
+
+msgid "Enter a number, 0 or more."
+msgstr "请输入大于或等于 0 的数字。"
+
+msgid "Enter a number."
+msgstr "请输入数字。"
+
+msgid "Enter a web address starting with https://."
+msgstr "请输入以 https:// 开头的网址。"
+
+msgid "Enter a whole number, 0 or more."
+msgstr "请输入大于或等于 0 的整数。"
+
+msgid "Enter an amount, like 1250 or 1250.50."
+msgstr "输入金额,例如 1250 或 1250.50。"
+
+msgid "Enter an email address, like name@example.com."
+msgstr "输入邮箱地址,例如 name@example.com。"
+
+msgid "Enter an email address."
+msgstr "请输入邮箱地址。"
+
+msgid "Enter one of the backup codes you saved when you turned on two-factor."
+msgstr "请输入开启双重验证时保存的任意一个备用恢复码。"
+
+msgid "Enter the 6 digits."
+msgstr "请输入 6 位数字。"
+
+msgid "Enter the 6-digit code from your authenticator app."
+msgstr "输入身份验证器应用中的 6 位数字验证码。"
+
+msgid "Enter the setup code"
+msgstr "输入设置码"
+
+msgid "Enter their name."
+msgstr "请输入对方的姓名。"
+
+msgid "Enter this key in the app instead:"
+msgstr "请改为在应用中输入此密钥:"
+
+msgid "Enter your email address to get a sign-in link."
+msgstr "输入你的邮箱地址以获取登录链接。"
+
+msgid "Enter your email address to reset your password."
+msgstr "输入你的电子邮箱以重置密码。"
+
+msgid "Enter your email or username."
+msgstr "输入你的邮箱或用户名。"
+
+msgid "Enter your name."
+msgstr "请输入你的姓名。"
+
+msgid "Enter your password to confirm it's you."
+msgstr "请输入密码以确认是你本人。"
+
+msgid "Enter your password."
+msgstr "请输入密码。"
+
+msgid "Enter your username."
+msgstr "请输入用户名。"
+
+msgid "Essentials"
+msgstr "基础模式"
+
+msgid "Euro"
+msgstr "欧元"
+
+msgid "Every addition, move and edit in the locations you belong to shows here, newest first."
+msgstr "你所属空间中的所有新增、移动和编辑记录都会按时间倒序显示在这里。"
+
+msgid "Every control Kept's screens are built from, on React Aria. Switch the theme and the language above: everything here should mirror cleanly."
+msgstr "Kept 界面基于 React Aria 构建的所有控件。在上方切换主题和语言:此处所有内容均应准确响应。"
+
+msgid "Every device {who} is signed in on is signed out. They get an email about it."
+msgstr "{who} 登录的所有设备都会退出登录,对方也会收到邮件通知。"
+
+msgid "Every result, with filters"
+msgstr "所有结果,支持筛选"
+
+msgid "Every room or spot has a kind. Give your own kinds fields, like a shelf's width or an air filter's size, and every place of that kind can record them."
+msgstr "每个房间或点位都有一种类型。为自定义类型添加字段(例如货架宽度或空气滤网尺寸)后,所有该类型的位置都能记录这些数据。"
+
+msgid "Every step is done."
+msgstr "所有步骤已完成。"
+
+msgid "Every value carries over."
+msgstr "所有值都会保留下来。"
+
+msgid "Everyone in {where}"
+msgstr "{where} 中的所有人"
+
+msgid "Everyone who could be an admin already is. Managed and disabled accounts can't be admins."
+msgstr "所有具备管理员资格的账号都已是管理员。受管账号与已停用账号不能成为管理员。"
+
+msgid "Everyone's"
+msgstr "所有人的"
+
+msgid "Everyone's · {0}"
+msgstr "所有人的 · {0}"
+
+msgid "Everything else"
+msgstr "其他全部"
+
+msgid "Everything in <0>{name}0> moves into the place you choose, and <1>{name}1> goes away. Its history stays with the things."
+msgstr "<0>{name}0> 中的所有物品都将移入你选定的位置,随后 <1>{name}1> 将被移除。历史记录会随物品一起保留。"
+
+msgid "Everything in Essentials"
+msgstr "Essentials 方案全部功能"
+
+msgid "Everything in Household"
+msgstr "Household 方案全部功能"
+
+msgid "Everything inside goes with it, and comes back with it on Restore."
+msgstr "其中的所有内容也会一并移入,还原时将随之一起恢复。"
+
+msgid "Everything is searched again when you're back online."
+msgstr "恢复联网后将自动重新搜索全部内容。"
+
+msgid "Everything that points at <0>{from}0> will point at the one you choose, and <1>{from}1> goes away. Its history stays with the things."
+msgstr "所有指向 <0>{from}0> 的记录都将改指向你所选的对象,随后 <1>{from}1> 将被删除,其历史记录会随物品保留。"
+
+msgid "Expand sidebar"
+msgstr "展开侧边栏"
+
+msgid "Expires"
+msgstr "过期时间"
+
+msgid "Expires on"
+msgstr "到期日"
+
+msgid "Failed {when} after {attempts} attempts"
+msgstr "于 {when} 失败(共尝试 {attempts} 次)"
+
+msgid "Failed jobs"
+msgstr "失败的任务"
+
+msgid "Failed jobs are rising"
+msgstr "失败任务数量正在上升"
+
+msgid "Fair"
+msgstr "一般"
+
+msgid "Field added"
+msgstr "已添加字段"
+
+msgid "Field archived"
+msgstr "已归档字段"
+
+msgid "Field changed"
+msgstr "字段已更改"
+
+msgid "Field groups"
+msgstr "字段分组"
+
+msgid "Field restored"
+msgstr "字段已恢复"
+
+msgid "Fields"
+msgstr "字段"
+
+msgid "Fields to archive"
+msgstr "待归档字段"
+
+msgid "File"
+msgstr "文件"
+
+msgid "File type"
+msgstr "文件类型"
+
+msgid "File uploaded"
+msgstr "文件已上传"
+
+msgid "Fill in by hand"
+msgstr "手动填写"
+
+msgid "Filled in by AI and accepted: {acceptedList}."
+msgstr "已采纳 AI 填充的字段:{acceptedList}。"
+
+msgid "Filter"
+msgstr "筛选"
+
+msgid "Filter by"
+msgstr "筛选条件"
+
+msgid "Filters"
+msgstr "筛选条件"
+
+msgid "Filters in use"
+msgstr "已启用的筛选条件"
+
+msgid "Find"
+msgstr "查找"
+
+msgid "Find a brand"
+msgstr "查找品牌"
+
+msgid "Find a filter"
+msgstr "查找筛选条件"
+
+msgid "Find a language"
+msgstr "查找语言"
+
+msgid "Find a location"
+msgstr "查找空间"
+
+msgid "Find a person"
+msgstr "查找联系人"
+
+msgid "Find a place"
+msgstr "查找位置"
+
+msgid "Find a tag"
+msgstr "查找分类标签"
+
+msgid "Find a type"
+msgstr "查找类型"
+
+msgid "Find a value"
+msgstr "查找数值"
+
+msgid "Find anything you've kept"
+msgstr "查找你保存过的任何物品"
+
+msgid "Finding things: rooms, boxes, labels and search."
+msgstr "查找物品:房间、收纳箱、标签与搜索。"
+
+msgid "Finding where you are…"
+msgstr "正在定位当前位置…"
+
+msgid "Fine-tune"
+msgstr "微调"
+
+msgid "Finish check"
+msgstr "完成清点"
+
+msgid "Finish setup"
+msgstr "完成设置"
+
+msgid "First {first} · last {last}"
+msgstr "首次 {first} · 最近 {last}"
+
+msgid "First account"
+msgstr "首个账号"
+
+msgid "Fix the reading"
+msgstr "修正读数"
+
+msgid "Fixed the reading"
+msgstr "已修正读数"
+
+msgid "Floor"
+msgstr "楼层"
+
+msgid "Follows this device’s light or dark setting."
+msgstr "跟随此设备的浅色或深色外观设置。"
+
+msgid "For a child or a parent with no email: they sign in with a username. You can reset their password later; they can add an email to take it over."
+msgstr "适合没有邮箱的儿童或长辈:他们可以使用用户名登录。你之后可以帮他们重置密码;他们也可以随时添加邮箱以接管账号。"
+
+msgid "For an account someone made for you. Enter your username and the code they gave you, then choose your password. The code works once."
+msgstr "适用于他人为你创建的账号。输入你的用户名和对方提供的重置码,然后设置密码。该重置码仅限使用一次。"
+
+msgid "For information"
+msgstr "仅供参考"
+
+msgid "For instance admins"
+msgstr "供实例管理员参考"
+
+msgid "Forgot their password? A new code lets them set another."
+msgstr "忘记密码?生成新验证码可让对方重设密码。"
+
+msgid "Forgot your password?"
+msgstr "忘记密码?"
+
+msgid "Found"
+msgstr "已找到"
+
+msgid "Found here · moves into this box"
+msgstr "在此找到 · 移入此箱子"
+
+msgid "Found here, from elsewhere"
+msgstr "在此处找到,但来自其他位置"
+
+msgid "Found it, or got it back: the end details are cleared."
+msgstr "已找回或收回:结束详情已清除。"
+
+msgid "Found something else"
+msgstr "发现了其他物品"
+
+msgid "From"
+msgstr "来自"
+
+msgid "From {0}"
+msgstr "来自 {0}"
+
+msgid "From {from}"
+msgstr "来自 {from}"
+
+msgid "From {from} · inherited"
+msgstr "来自 {from} · 继承"
+
+msgid "From the {kindLabel} template. Rename, remove or add; change them any time."
+msgstr "来自“{kindLabel}”模板。可重命名、移除或新增,随时调整。"
+
+msgid "From the label · tap to change"
+msgstr "来自标签 · 轻点更改"
+
+msgid "From this phone, as of last sync {0}"
+msgstr "来自此手机,截至上次同步 {0}"
+
+msgid "from this phone, as of last sync {asOf}"
+msgstr "来自此手机,数据截至上次同步:{asOf}"
+
+msgid "Front"
+msgstr "正面"
+
+msgid "Fuel"
+msgstr "燃油"
+
+msgid "Fuel station"
+msgstr "加油站"
+
+msgid "Full width"
+msgstr "全宽"
+
+msgid "Full width gives lists and tables the whole screen. Text and forms keep a readable width."
+msgstr "全宽模式下列表和表格将铺满屏幕,正文与表单仍保持易读宽度。"
+
+msgid "Gallery"
+msgstr "相册"
+
+msgid "Garage"
+msgstr "车库"
+
+msgid "Garage › Wall shelf › Blue bin"
+msgstr "车库 › 墙面置物架 › 蓝色收纳箱"
+
+msgid "General"
+msgstr "通用"
+
+msgid "Get started"
+msgstr "开始使用"
+
+msgid "Get-started checklist"
+msgstr "入门检查清单"
+
+msgid "Give {person} this code"
+msgstr "将此重置码交给 {person}"
+
+msgid "Give {who} a new one-time code?"
+msgstr "要为 {who} 生成新的一次性验证码吗?"
+
+msgid "Give {who} this code"
+msgstr "将此代码提供给 {who}"
+
+msgid "Give it a label ID"
+msgstr "为其设置标签 ID"
+
+msgid "Give it a name, like Cables or This week."
+msgstr "起个名字,例如「线缆」或「本周」。"
+
+msgid "Give it a name, like Home or Garage."
+msgstr "起个名字,比如「家」或「车库」。"
+
+msgid "Give it a name, like Shelf A or Balcony."
+msgstr "输入名称,例如“A 号货架”或“阳台”。"
+
+msgid "Give it a name."
+msgstr "请填写名称。"
+
+msgid "Give the box a name, like Box 3."
+msgstr "给箱子起个名字,例如「3 号箱」。"
+
+msgid "Give the box a name."
+msgstr "请为箱子命名。"
+
+msgid "Give the field a label, like Screen size."
+msgstr "给字段起个名称,例如“屏幕尺寸”。"
+
+msgid "Give the kind a name, like Shelf or Bay."
+msgstr "为该类型起一个名称,例如「货架」或「库位」。"
+
+msgid "Give the type a name, like Board game."
+msgstr "为类型起一个名称,例如「桌游」。"
+
+msgid "Give these a place"
+msgstr "为这些物品分配位置"
+
+msgid "Given away"
+msgstr "已赠送"
+
+msgid "Given to"
+msgstr "交给"
+
+msgid "Go to Home"
+msgstr "前往首页"
+
+msgid "Go to Kept"
+msgstr "前往 Kept"
+
+msgid "Go to Settings"
+msgstr "前往设置"
+
+msgid "Go to sign in"
+msgstr "前往登录"
+
+msgid "Goes for good on {purge}"
+msgstr "将于 {purge} 彻底清除"
+
+msgid "Good"
+msgstr "良好"
+
+msgid "Got it"
+msgstr "知道了"
+
+msgid "Groq listed it at USD {input} per million input tokens and {output} per million output tokens on {listed}. You can change it in the price table."
+msgstr "Groq 于 {listed} 公布的公开价格为:输入每百万 tokens {input} 美元,输出每百万 tokens {output} 美元。你可以在价格表中修改。"
+
+msgid "Group"
+msgstr "分组"
+
+msgid "Hallway"
+msgstr "走廊"
+
+msgid "Has a Kept account"
+msgstr "已有 Kept 账号"
+
+msgid "Has a reading that grows, like kilometres or hours."
+msgstr "包含累计递增的读数,例如里程数或运行小时数。"
+
+msgid "Has accessory"
+msgstr "包含配件"
+
+msgid "Has an expiry date to be reminded about."
+msgstr "包含需提醒的到期日。"
+
+msgid "Has spare part"
+msgstr "配有备件"
+
+msgid "Have you kept the recovery kit?"
+msgstr "你是否已妥善保存恢复工具包?"
+
+msgid "Help"
+msgstr "帮助"
+
+msgid "hidden"
+msgstr "已隐藏"
+
+msgid "Hidden"
+msgstr "已隐藏"
+
+msgid "Hidden from Home."
+msgstr "已从首页隐藏。"
+
+msgid "Hide now"
+msgstr "立即隐藏"
+
+msgid "Hide password"
+msgstr "隐藏密码"
+
+msgid "Hides in {0} s, and at once if you leave this page."
+msgstr "将在 {0} 秒后隐藏;离开此页面则会立即隐藏。"
+
+msgid "Higher than the reading after it"
+msgstr "高于其后的读数"
+
+msgid "Higher than the reading after it ({after} {unit}). Check the value and the date it was taken."
+msgstr "高于后一条读数({after} {unit})。请核对数值以及记录日期。"
+
+msgid "History"
+msgstr "历史记录"
+
+msgid "AI call records landed outside a monthly partition"
+msgstr "部分 AI 调用记录落在了按月分区之外"
+
+msgid "The nightly backup failed"
+msgstr "夜间备份失败"
+
+msgid "The old label keeps working."
+msgstr "旧标签仍可继续使用。"
+
+msgid "{n} rows in llm_calls_default. Move them into their month's partition as kept_owner; the alert then resolves."
+msgstr "llm_calls_default 中有 {n} 行记录。请以 kept_owner 身份将它们移入对应月份的分区,之后此告警将自动解除。"
+
+msgid "Last good backup {lastOk}. The next good run resolves this alert."
+msgstr "上次成功备份:{lastOk}。下次成功运行即可解除此提醒。"
+
+msgid "No backup has succeeded yet. The next good run resolves this alert."
+msgstr "尚无成功的备份。下次正常备份后将解除此警报。"
+
+msgid "History rows landed outside a monthly partition"
+msgstr "部分历史记录落在了月度分区之外"
+
+msgid "Hold steady · fill the frame · original kept"
+msgstr "持稳手机 · 尽量占满画面 · 原图将保留"
+
+msgid "Home"
+msgstr "首页"
+
+msgid "Hours"
+msgstr "小时"
+
+msgid "House"
+msgstr "住宅"
+
+msgid "Household"
+msgstr "家庭"
+
+msgid "How"
+msgstr "方式"
+
+msgid "How many to take off"
+msgstr "要取出的数量"
+
+msgid "How should this Kept work?"
+msgstr "希望如何配置此 Kept 实例?"
+
+msgid "How to allow it"
+msgstr "如何开启权限"
+
+msgid "I have a one-time code"
+msgstr "我有一次性代码"
+
+msgid "I have an account: sign in"
+msgstr "已有账号:登录"
+
+msgid "I've kept it"
+msgstr "我已保留"
+
+msgid "I've kept it somewhere else"
+msgstr "我已将它保存在其他地方"
+
+msgid "I've saved them"
+msgstr "我已保存"
+
+msgid "Icon"
+msgstr "图标"
+
+msgid "Icons"
+msgstr "图标"
+
+msgid "ID chip and status"
+msgstr "ID 芯片与状态"
+
+msgid "ID pending"
+msgstr "编号待分配"
+
+msgid "Identity"
+msgstr "身份标识"
+
+msgid "If <0>{to}0> has an account here, a link to set a new password is on its way. It works once, for an hour."
+msgstr "如果 <0>{to}0> 在此处已有账号,一封用于设置新密码的链接邮件正在发送中。该链接在 1 小时内仅限使用一次。"
+
+msgid "If <0>{to}0> has an account here, a sign-in link is on its way. It works once, for 15 minutes."
+msgstr "如果 <0>{to}0> 在此已有账号,登录链接正在发送中。链接仅一次有效,有效期 15 分钟。"
+
+msgid "If that disk fails, the backups go with it. Point the backup at another disk."
+msgstr "如果该磁盘损坏,备份也会一并丢失。请将备份路径指向另一块磁盘。"
+
+msgid "If you lose your phone, each of these signs you in once. Keep them somewhere other than this phone: a password manager or a printed page."
+msgstr "如果不慎遗失手机,每个恢复码都可用于单次登录。请将它们妥善保存在手机之外的地方:例如密码管理器或打印纸页。"
+
+msgid "Import"
+msgstr "导入"
+
+msgid "In {addToName}"
+msgstr "位于 {addToName}"
+
+msgid "In a sentence: the drill <0/> is on the tool wall."
+msgstr "示例句:电钻 <0/> 在工具墙上。"
+
+msgid "In Chrome or Edge, click the install icon at the end of the address bar, or open the menu and choose <0>Install Kept0>."
+msgstr "在 Chrome 或 Edge 中,点击地址栏末端的安装图标,或打开菜单选择<0>安装 Kept0>。"
+
+msgid "In Safari on a Mac, choose <0>File › Add to Dock0>."
+msgstr "在 Mac 版 Safari 中,选择<0>文件 › 添加到程序坞0>。"
+
+msgid "In the tray"
+msgstr "在托盘中"
+
+msgid "In use"
+msgstr "使用中"
+
+msgid "Inbox"
+msgstr "收件箱"
+
+msgid "Include ended things"
+msgstr "包含已结束物品"
+
+msgid "Include things in the Trash"
+msgstr "包含回收站中的物品"
+
+msgid "Inherited"
+msgstr "继承"
+
+msgid "Inside"
+msgstr "内部"
+
+msgid "Inside <0>{0}0>"
+msgstr "位于 <0>{0}0> 内"
+
+msgid "Insights"
+msgstr "统计洞察"
+
+msgid "Install Kept"
+msgstr "安装 Kept"
+
+msgid "Install Kept on your phone"
+msgstr "在手机上安装 Kept"
+
+msgid "Install on your phone"
+msgstr "安装到手机"
+
+msgid "Installed on your phone"
+msgstr "已安装到你的手机"
+
+msgid "Instance admin"
+msgstr "实例管理员"
+
+msgid "Instance admins"
+msgstr "实例管理员"
+
+msgid "Instance admins run this server: users, sign-up, jobs and alerts. Being one doesn't open anyone's locations; they see only the locations they are members of."
+msgstr "实例管理员负责管理此服务器的用户、注册、后台任务与告警。成为实例管理员并不会打开他人的空间;他们只能看到自己所属的空间。"
+
+msgid "Instance options"
+msgstr "实例选项"
+
+msgid "Invite"
+msgstr "邀请"
+
+msgid "Invite changed"
+msgstr "已更新邀请"
+
+msgid "Invite created"
+msgstr "已创建邀请"
+
+msgid "Invite people to {name}"
+msgstr "邀请成员加入 {name}"
+
+msgid "Invite revoked"
+msgstr "邀请已撤销"
+
+msgid "Invite someone"
+msgstr "邀请成员"
+
+msgid "Invite to {name}"
+msgstr "邀请加入 {name}"
+
+msgid "Invited someone"
+msgstr "已邀请成员"
+
+msgid "Invoice"
+msgstr "发票"
+
+msgid "iPhone doesn't let web apps appear in the Share sheet. Save the photo first, then add it in Capture with Gallery."
+msgstr "iPhone 不允许网页应用出现在系统分享菜单中。请先保存照片,再在「采集」中通过相册添加。"
+
+msgid "iPhone doesn't let web apps appear in the Share sheet. To add a receipt from another app, save it, then use Gallery in Capture."
+msgstr "iPhone 不允许网页应用出现在系统“分享”菜单中。要从其他 App 添加收据,请先保存到相册,再使用“采集”中的“图库”。"
+
+msgid "iPhone photos (HEIC)"
+msgstr "iPhone 照片 (HEIC)"
+
+msgid "iPhone, iPad"
+msgstr "iPhone、iPad"
+
+msgid "iPhone: Settings › Safari › Camera › Allow, then reopen Kept."
+msgstr "iPhone:前往「设置 › Safari 浏览器 › 相机 › 允许」,然后重新打开 Kept。"
+
+msgid "is any of"
+msgstr "属于以下任意一项"
+
+msgid "is none of"
+msgstr "不属于"
+
+msgid "it"
+msgstr "它"
+
+msgid "It can't be restored afterwards. Its history stays, without it."
+msgstr "删除后将无法恢复。历史记录仍会保留,但不含此项本身。"
+
+msgid "It comes off {0}. The file itself stays until it's purged."
+msgstr "它会从 {0} 解除关联。文件本身会一直保留,直到被彻底清理。"
+
+msgid "It depended on another change that couldn't apply."
+msgstr "它依赖另一项未能应用的更改。"
+
+msgid "It goes for everyone it's shared with. The things it finds stay."
+msgstr "所有被共享者都将无法再访问。它所找到的物品仍会保留。"
+
+msgid "It goes for everyone it's shared with. What it shows stays."
+msgstr "对所有已分享该链接的人立即失效。已展示的内容会保留。"
+
+msgid "It goes to the trash with its photos. You can restore it for 30 days."
+msgstr "该项及其照片将移入回收站。30 天内可随时恢复。"
+
+msgid "It has already synced. Undo it from the thing's history."
+msgstr "此操作已同步。请在对应物品的历史记录中撤销。"
+
+msgid "It has meters"
+msgstr "包含表计"
+
+msgid "It inherits the capabilities and fields of the type it sits inside."
+msgstr "它会继承其所在父级类型的功能与字段。"
+
+msgid "It is removed from the meter's history."
+msgstr "已从该表计的历史记录中移除。"
+
+msgid "It leaves this location"
+msgstr "它将离开此空间"
+
+msgid "It left no error message."
+msgstr "未留下任何错误信息。"
+
+msgid "It moves into this box when you finish."
+msgstr "完成后它会自动移入此箱子。"
+
+msgid "It shows as \"not sure where\" until someone sees it."
+msgstr "在有人确认看到之前,它会显示为“不确定在哪”。"
+
+msgid "It shows under Members as a pending invite until it's used, where you can revoke it."
+msgstr "在被使用前,它会在「成员」下显示为待接受邀请,你可在那里撤销。"
+
+msgid "It stays in your saved views."
+msgstr "它将保留在你的已保存视图中。"
+
+msgid "It stays there for 30 days."
+msgstr "它将在那里保留 30 天。"
+
+msgid "It was kept for {hours} hours and has been removed. Make it again."
+msgstr "文件仅保留 {hours} 小时并已被清理。请重新生成。"
+
+msgid "It was too big to finish. Choose some places, types or tags to make it smaller."
+msgstr "内容过大,无法一次完成。请筛选部分位置、类型或分类标签以缩小范围。"
+
+msgid "It was used, revoked, or it's more than 7 days old. Ask the person who sent it for a new one."
+msgstr "该邀请已被使用、被撤销,或已超过 7 天有效期。请联系发送人重新发送邀请。"
+
+msgid "It will check when you're online."
+msgstr "联网后将自动检查。"
+
+msgid "Check the code"
+msgstr "检查编码"
+
+msgid "This phone doesn't have this code."
+msgstr "此手机上没有该编码。"
+
+msgid "None of your labels has this code."
+msgstr "你的标签中没有此编码。"
+
+msgid "Is this the code?"
+msgstr "是这个编码吗?"
+
+msgid "Read from the printed text, not a QR code. Check it against the label."
+msgstr "这是从印刷文字识别的,而非二维码。请对照实物标签核对。"
+
+msgid "That's the code"
+msgstr "验证码正确"
+
+msgid "It will need your password or passkey to get back in."
+msgstr "之后需要重新使用密码或通行密钥才能登录。"
+
+msgid "It won't run again. Whatever it was doing stays undone."
+msgstr "它不会再次运行,尚未完成的任务将保持未完成状态。"
+
+msgid "It's empty. You can restore it from Trash for 30 days."
+msgstr "里面是空的。你可以在 30 天内从回收站恢复。"
+
+msgid "It's kept for {hours} hours."
+msgstr "将保留 {hours} 小时。"
+
+msgid "It's pending until it syncs. If another phone claimed it first, you'll be told."
+msgstr "在同步完成前将处于待处理状态。如果另一台手机已先领用该标签,系统会提示你。"
+
+msgid "Its fields show on every type that uses the group."
+msgstr "该字段组中的字段会显示在所有使用它的类型上。"
+
+msgid "Its ID arrives when it syncs."
+msgstr "同步完成后将获得其 ID。"
+
+msgid "Its ID is still being made. Try again in a moment."
+msgstr "其 ID 仍在生成中,请稍后再试。"
+
+msgid "Its things move to the type you choose and take its fields; values the other type doesn't have are archived, not lost. Then <0>{name}0> is gone."
+msgstr "其下物品将迁至你选择的类型并套用该类型的字段;目标类型没有的字段值将被归档而不会丢失。随后 <0>{name}0> 将被删除。"
+
+msgid "Its type, tags and shop are copied into the other home's lists."
+msgstr "其类型、分类标签和商家会复制到另一个空间的列表中。"
+
+msgid "Join {name}"
+msgstr "加入 {name}"
+
+msgid "Join {place} on Kept"
+msgstr "加入 Kept 上的 {place}"
+
+msgid "joined {joined}"
+msgstr "加入于 {joined}"
+
+msgid "Joined {joinedName}"
+msgstr "已加入 {joinedName}"
+
+msgid "Joining someone's Kept?"
+msgstr "受邀加入他人的 Kept?"
+
+msgid "Jump to"
+msgstr "跳转至"
+
+msgid "Keep"
+msgstr "保留"
+
+msgid "Keep as"
+msgstr "保留为"
+
+msgid "Keep both"
+msgstr "两者都保留"
+
+msgid "Keep capturing"
+msgstr "继续采集"
+
+msgid "Keep it"
+msgstr "保留"
+
+msgid "Keep mine"
+msgstr "保留我的"
+
+msgid "Keep notes to 5,000 characters."
+msgstr "备注请控制在 5,000 个字符以内。"
+
+msgid "Keep the label to 80 characters."
+msgstr "标签文本请控制在 80 个字符以内。"
+
+msgid "Keep the name to {max} characters."
+msgstr "名称最多 {max} 个字符。"
+
+msgid "Keep the name to 80 characters."
+msgstr "名称请控制在 80 个字符以内。"
+
+msgid "Keep the name under 120 characters."
+msgstr "名称请控制在 120 个字符以内。"
+
+msgid "Keep the name under 200 characters."
+msgstr "请将名称控制在 200 个字符以内。"
+
+msgid "Keep the phone number to 40 characters."
+msgstr "电话号码请勿超过 40 个字符。"
+
+msgid "Keep the unit short, like cm or W."
+msgstr "单位请保持简短,例如 cm 或 W。"
+
+msgid "Keep theirs"
+msgstr "保留对方更改"
+
+msgid "Keep your backup codes"
+msgstr "妥善保存备用恢复码"
+
+msgid "Kept"
+msgstr "Kept"
+
+msgid "Kept apart and encrypted, and revealed only per its policy. Only you, the account owner, can make a field secret, and only now."
+msgstr "单独加密保存,仅按策略显示。只有账号拥有者(你)才能将字段设为私密,且仅限现在设置。"
+
+msgid "Kept both"
+msgstr "已保留两者"
+
+msgid "Kept can't scan here"
+msgstr "Kept 无法在此处扫码"
+
+msgid "Kept can't tell what this is from here."
+msgstr "Kept 从这里无法判断它是什么。"
+
+msgid "Kept can't use the camera"
+msgstr "Kept 无法使用摄像头"
+
+msgid "Kept from an earlier type. They're not lost; re-type back to use them again."
+msgstr "保留自先前的类型,并未丢失;重新改回原类型即可再次使用。"
+
+msgid "Kept label in view"
+msgstr "画面中有 Kept 标签"
+
+msgid "Kept limits admin actions over HTTP. Put Kept on HTTPS before you rely on them."
+msgstr "Kept 会在 HTTP 下限制管理员操作。依赖这些功能前,请先为 Kept 启用 HTTPS。"
+
+msgid "Kept makes at most five reports an hour. Try again later."
+msgstr "Kept 每小时最多生成五份报告,请稍后再试。"
+
+msgid "Kept needs at least one instance admin"
+msgstr "Kept 至少需要保留一名实例管理员"
+
+msgid "Kept needs at least one instance admin, so the last one can't be removed."
+msgstr "Kept 至少需要一名实例管理员,因此无法移除最后一位管理员。"
+
+msgid "Kept on the server is older than this app; ask your admin."
+msgstr "服务器上的 Kept 版本低于此应用,请联系管理员更新。"
+
+msgid "Kept opens from its own icon, full screen, and works offline."
+msgstr "Kept 将以独立图标全屏打开,并支持离线使用。"
+
+msgid "Kept raises an alert here, and emails the instance admins at most once a day, when something on the server needs a person."
+msgstr "当服务器出现需要人工处理的事项时,Kept 会在此发出告警,并每天最多向实例管理员发送一封邮件通知。"
+
+msgid "Kept safe"
+msgstr "保存完好"
+
+msgid "Kept sends no email: no sign-in links, password resets, email invites or alerts. Set <0>KEPT_SMTP_URL0> and restart Kept. Link invites and passwords work without it."
+msgstr "Kept 无法发送邮件:包括登录链接、密码重置、邮件邀请与告警通知。请设置 <0>KEPT_SMTP_URL0> 并重启 Kept。链接邀请与密码登录不受影响。"
+
+msgid "Kept stores the barcode with it."
+msgstr "Kept 会一并保存该条形码。"
+
+msgid "Kept takes photos and PDFs. Share those, or use Gallery."
+msgstr "Kept 支持照片和 PDF。请分享这些文件,或使用系统相册。"
+
+msgid "Kept the reading"
+msgstr "已保留读数"
+
+msgid "Kept wasn't ready to receive files on this device yet. It is now: go back to the other app and share again."
+msgstr "Kept 在此设备上尚未准备好接收文件。现在已就绪:请回到刚才的应用重新分享。"
+
+msgid "Key"
+msgstr "密钥"
+
+msgid "Key <0>{0}0> · {1}"
+msgstr "密钥 <0>{0}0> · {1}"
+
+msgid "Keyboard shortcuts"
+msgstr "键盘快捷键"
+
+msgid "Keys do nothing while you type in a field."
+msgstr "在输入框中输入时,快捷键不会生效。"
+
+msgid "Kind"
+msgstr "类型"
+
+msgid "Kind of file"
+msgstr "文件类型"
+
+msgid "Kitchen"
+msgstr "厨房"
+
+msgid "Label"
+msgstr "标签"
+
+msgctxt "field name"
+msgid "Label"
+msgstr "标签"
+
+msgid "Label {0}"
+msgstr "标签 {0}"
+
+msgid "Label <0/>"
+msgstr "标签 <0/>"
+
+msgid "Label already claimed"
+msgstr "标签已被认领"
+
+msgid "Label assigned"
+msgstr "已分配标签"
+
+msgid "Label claimed for {label}"
+msgstr "已为 {label} 认领标签"
+
+msgid "Label claimed for {label} on this phone"
+msgstr "已在此手机上为 {label} 领用标签"
+
+msgid "Label claims"
+msgstr "标签认领"
+
+msgid "Label ID"
+msgstr "标签 ID"
+
+msgid "Label ID {code} is ready"
+msgstr "标签 ID {code} 已就绪"
+
+msgid "Labelled {name}"
+msgstr "已为 {name} 分配标签"
+
+msgid "Labels"
+msgstr "标签"
+
+msgid "Labels & QR"
+msgstr "标签与二维码"
+
+msgid "Labels and QR codes"
+msgstr "标签与二维码"
+
+msgid "Language"
+msgstr "语言"
+
+msgid "Languages"
+msgstr "语言"
+
+msgid "Languages spoken here"
+msgstr "这里使用的语言"
+
+msgid "Last 30 days"
+msgstr "最近 30 天"
+
+msgid "Last 7 days"
+msgstr "最近 7 天"
+
+msgid "Last answer: {lastConfirm}"
+msgstr "上次回复:{lastConfirm}"
+
+msgid "Last day"
+msgstr "最后一天"
+
+msgid "Last place · tap to change"
+msgstr "上次位置 · 轻点更改"
+
+msgid "Last saved: {lastName} · ID pending"
+msgstr "上次保存:{lastName} · ID 待分配"
+
+msgid "Last seen"
+msgstr "上次看到"
+
+msgctxt "Display button"
+msgid "Last seen"
+msgstr "上次见到"
+
+msgid "Later readings count on from it, so this one fits."
+msgstr "后续读数顺延递增,因此此读数合理。"
+
+msgid "latest, {0}"
+msgstr "最新,{0}"
+
+msgid "Layout"
+msgstr "布局"
+
+msgid "Leave {0} out"
+msgstr "排除 {0}"
+
+msgid "Leave {name}"
+msgstr "退出 {name}"
+
+msgid "Leave {name}?"
+msgstr "退出 {name}?"
+
+msgid "Leave this location"
+msgstr "退出此空间"
+
+msgid "Lending"
+msgstr "借出"
+
+msgid "Lent"
+msgstr "已借出"
+
+msgid "Lent to Ibrahim"
+msgstr "已借给 Ibrahim"
+
+msgid "Let anyone with the address create an account"
+msgstr "允许任何访问此地址的人创建账号"
+
+msgid "Light"
+msgstr "浅色"
+
+msgid "Like a MAC address for Wi-Fi and one for Ethernet."
+msgstr "例如一个 Wi-Fi MAC 地址和一个有线网卡 MAC 地址。"
+
+msgid "Likely duplicate"
+msgstr "疑似重复"
+
+msgid "Lines don't add up"
+msgstr "各明细行之和与总额不符"
+
+msgid "Link"
+msgstr "链接"
+
+msgid "Link {0} to another thing"
+msgstr "将 {0} 关联到另一件物品"
+
+msgid "Link a charger to its phone, a spare part to its machine, or a set that belongs together."
+msgstr "将充电器关联到手机、备件关联到设备,或把成套物品关联在一起。"
+
+msgid "Link a receipt line"
+msgstr "关联收据明细"
+
+msgid "Link a thing"
+msgstr "关联物品"
+
+msgid "Link copied"
+msgstr "已复制链接"
+
+msgid "Link expires {expires}"
+msgstr "链接将于 {expires} 过期"
+
+msgid "Link removed"
+msgstr "链接已移除"
+
+msgid "Link sent"
+msgstr "链接已发送"
+
+msgid "Link to an existing thing"
+msgstr "关联到现有物品"
+
+msgid "Linked"
+msgstr "已关联"
+
+msgid "Linked {name}"
+msgstr "已关联 {name}"
+
+msgid "Linked to a purchase"
+msgstr "已关联购买记录"
+
+msgid "links"
+msgstr "个关联"
+
+msgid "Links"
+msgstr "链接"
+
+msgid "List"
+msgstr "列表"
+
+msgid "List surface"
+msgstr "列表视图"
+
+msgid "List the choices, separated by commas."
+msgstr "列出可选项,用英文逗号分隔。"
+
+msgid "Living room"
+msgstr "客厅"
+
+msgid "Load more"
+msgstr "加载更多"
+
+msgid "Loading"
+msgstr "正在加载"
+
+msgid "Loading {label}"
+msgstr "正在加载 {label}"
+
+msgid "Loading icons"
+msgstr "正在加载图标"
+
+msgid "Loading places"
+msgstr "正在加载位置"
+
+msgid "Loading the box"
+msgstr "正在加载箱子"
+
+msgid "Loading the invite"
+msgstr "正在加载邀请"
+
+msgid "Loading the thing"
+msgstr "正在加载物品"
+
+msgid "Loading the type"
+msgstr "正在加载类型"
+
+msgid "Loading types"
+msgstr "正在加载类型"
+
+msgid "Loading what needs you"
+msgstr "正在加载待办事项"
+
+msgid "Loading your devices"
+msgstr "正在加载你的设备"
+
+msgid "Loading your locations"
+msgstr "正在加载你的空间"
+
+msgid "Loading…"
+msgstr "加载中…"
+
+msgid "Location"
+msgstr "空间"
+
+msgid "Location access is off for Kept in this browser's settings."
+msgstr "此浏览器设置中已关闭 Kept 的定位权限。"
+
+msgid "Location created"
+msgstr "空间已创建"
+
+msgid "Location deleted"
+msgstr "空间已删除"
+
+msgid "Location permission"
+msgstr "定位权限"
+
+msgid "Location restored"
+msgstr "空间已恢复"
+
+msgid "Location settings"
+msgstr "空间设置"
+
+msgid "Location settings changed"
+msgstr "空间设置已更改"
+
+msgid "Locations"
+msgstr "空间"
+
+msgid "Log a reading"
+msgstr "记录读数"
+
+msgid "Log a reading · {0}"
+msgstr "记录读数 · {0}"
+
+msgid "Log the first one to start its history."
+msgstr "记录第一条数据即可开始积累历史记录。"
+
+msgid "Long unseen"
+msgstr "长期未查看"
+
+msgid "Looking it up needs a connection."
+msgstr "查询该信息需要网络连接。"
+
+msgid "Looking it up…"
+msgstr "正在查询…"
+
+msgid "Lost"
+msgstr "已遗失"
+
+msgid "Lost the logs? Issue a new one with <0>kept admin setup-code0>."
+msgstr "找不到日志了?可使用 <0>kept admin setup-code0> 重新生成。"
+
+msgid "Lower than the reading before it"
+msgstr "低于前一条读数"
+
+msgid "Lower than the reading before it ({before} {unit}). Check the value, or record that the meter was replaced first."
+msgstr "低于前一条读数({before} {unit})。请核对数值,或先记录表计已更换。"
+
+msgid "Made {n}"
+msgstr "已创建 {n}"
+
+msgid "Made from"
+msgstr "转换来源"
+
+msgid "Mail"
+msgstr "邮件"
+
+msgid "Mail isn't configured"
+msgstr "邮件服务未配置"
+
+msgid "Main"
+msgstr "主页"
+
+msgid "Make {who} an instance admin?"
+msgstr "要将 {who} 设为实例管理员吗?"
+
+msgid "Make admin"
+msgstr "设为管理员"
+
+msgid "Make someone an admin"
+msgstr "将成员设为管理员"
+
+msgid "Make someone else an admin first, then remove {who}."
+msgstr "请先将其他人设为管理员,然后再移除 {who}。"
+
+msgid "Make the kind"
+msgstr "创建位置类型"
+
+msgid "Make the PDF"
+msgstr "生成 PDF"
+
+msgid "Make the type"
+msgstr "创建类型"
+
+msgid "Making the PDF"
+msgstr "正在生成 PDF"
+
+msgid "Making the PDF…"
+msgstr "正在生成 PDF…"
+
+msgid "Manage"
+msgstr "管理"
+
+msgid "Manage {who}"
+msgstr "管理 {who}"
+
+msgid "Managed account"
+msgstr "托管账号"
+
+msgid "Managed account · by {by}"
+msgstr "受管账号 · 由 {by} 管理"
+
+msgid "Managed account created"
+msgstr "已创建托管账号"
+
+msgid "Managed and disabled accounts can't be admins."
+msgstr "受管账户与已停用账户不能设为管理员。"
+
+msgid "Manual"
+msgstr "说明书"
+
+msgid "Manual (web address)"
+msgstr "说明书(网址)"
+
+msgid "Mark seen"
+msgstr "标记为已见到"
+
+msgid "Marked {name} as {status}"
+msgstr "已将 {name} 标为 {status}"
+
+msgid "Marked {name} as not here"
+msgstr "已将 {name} 标记为不在此处"
+
+msgid "Marked as not here"
+msgstr "已标记为不在此处"
+
+msgid "Marked as seen"
+msgstr "已标为已查看"
+
+msgid "Match"
+msgstr "匹配"
+
+msgid "matched: <0>{0}0>"
+msgstr "匹配到:<0>{0}0>"
+
+msgid "matched: <0><1/>0>"
+msgstr "匹配:<0><1/>0>"
+
+msgid "Matches"
+msgstr "匹配结果"
+
+msgid "Me"
+msgstr "我"
+
+msgid "Member"
+msgstr "成员"
+
+msgid "Member joined"
+msgstr "成员已加入"
+
+msgid "Member left"
+msgstr "成员已退出"
+
+msgid "member of {n}"
+msgstr "{n} 的成员"
+
+msgid "Member's role changed"
+msgstr "已更改成员角色"
+
+msgid "Members"
+msgstr "成员"
+
+msgid "Members add, move and edit things. They can't change settings or people."
+msgstr "成员可添加、移动和编辑物品,但无法更改设置或管理成员。"
+
+msgid "Members and roles"
+msgstr "成员与角色"
+
+msgid "Members of {where} see it too. Each still sees only what they may."
+msgstr "{where} 的成员也能看到它,但每人仅限查看各自权限范围内的内容。"
+
+msgid "Membership ended"
+msgstr "成员资格已结束"
+
+msgid "Merge"
+msgstr "合并"
+
+msgid "Merge {name} into {into}?"
+msgstr "将 {name} 合并到 {into}?"
+
+msgid "Merge {name} into…"
+msgstr "将 {name} 合并到…"
+
+msgid "Merge a duplicate"
+msgstr "合并重复项"
+
+msgid "Merge into"
+msgstr "合并到"
+
+msgid "Merge into {0}"
+msgstr "合并到 {0}"
+
+msgid "Merge into {into}"
+msgstr "合并到 {into}"
+
+msgid "Merge into {survivorName}"
+msgstr "合并到 {survivorName}"
+
+msgid "Merge into another place"
+msgstr "合并到其他位置"
+
+msgid "Merge into…"
+msgstr "合并到…"
+
+msgid "Merged {from} into {into}"
+msgstr "已将 {from} 合并到 {into}"
+
+msgid "Merged {name} into {into}"
+msgstr "已将 {name} 合并到 {into}"
+
+msgid "Merged {name} into another place"
+msgstr "已将 {name} 合并到另一个位置"
+
+msgid "Merged into {survivorName}"
+msgstr "已合并至 {survivorName}"
+
+msgid "Meter"
+msgstr "表计"
+
+msgid "Meter added"
+msgstr "已添加表计"
+
+msgid "Meter changed"
+msgstr "表计已更改"
+
+msgid "Meter replaced"
+msgstr "表计已更换"
+
+msgid "Metered"
+msgstr "带表计"
+
+msgid "meters"
+msgstr "米"
+
+msgid "Meters"
+msgstr "表计"
+
+msgid "Mine"
+msgstr "我的"
+
+msgid "Mine · {0}"
+msgstr "我的 · {0}"
+
+msgid "model"
+msgstr "型号"
+
+msgid "Model"
+msgstr "型号"
+
+msgctxt "ai model"
+msgid "Model"
+msgstr "型号"
+
+msgid "Money"
+msgstr "金额"
+
+msgid "Money and spending"
+msgstr "金额与支出"
+
+msgid "Months as a whole number, like 24."
+msgstr "以整数表示的月数,例如 24。"
+
+msgid "More"
+msgstr "更多"
+
+msgid "More actions"
+msgstr "更多操作"
+
+msgid "Most per day"
+msgstr "单日最高"
+
+msgid "move"
+msgstr "移动"
+
+msgid "Move"
+msgstr "移动"
+
+msgid "Move {0}"
+msgstr "移动 {0}"
+
+msgid "Move {0} to Trash?"
+msgstr "将 {0} 移入回收站?"
+
+msgid "Move {name} into…"
+msgstr "将 {name} 移至…"
+
+msgid "Move {name} to the trash?"
+msgstr "要将 {name} 移入回收站吗?"
+
+msgid "Move {names}"
+msgstr "移动 {names}"
+
+msgid "Move here"
+msgstr "移至此处"
+
+msgid "Move into"
+msgstr "移入"
+
+msgid "Move them to"
+msgstr "将其移至"
+
+msgid "Move them to {here}, then trash it"
+msgstr "将里面的物品移至 {here},然后移入回收站"
+
+msgid "Move them to <0>{targetName}0>"
+msgstr "将其移至<0>{targetName}0>"
+
+msgid "Move to the top level"
+msgstr "移至顶层"
+
+msgid "Move to trash"
+msgstr "移入回收站"
+
+msgid "Move to Trash"
+msgstr "移入回收站"
+
+msgid "Move to…"
+msgstr "移至…"
+
+msgid "Move undone"
+msgstr "已撤销搬家"
+
+msgid "Moved"
+msgstr "已移动"
+
+msgid "Moved {name}"
+msgstr "已移动 {name}"
+
+msgid "Moved {name} to another location"
+msgstr "已将 {name} 移至另一个空间"
+
+msgid "Moved {names}"
+msgstr "已移动 {names}"
+
+msgid "Moved {what} to {to}"
+msgstr "已将 {what} 移至 {to}"
+
+msgid "Moved in from another location"
+msgstr "从其他空间移入"
+
+msgid "Moved into {where}"
+msgstr "已移入 {where}"
+
+msgid "Moved to {where}"
+msgstr "已移至 {where}"
+
+msgid "Moved to Garage"
+msgstr "已移至车库"
+
+msgid "Moved to the top level"
+msgstr "已移至顶层"
+
+msgid "Moving house"
+msgstr "搬家打包"
+
+msgid "Moving…"
+msgstr "正在移动…"
+
+msgid "name"
+msgstr "名称"
+
+msgid "Name"
+msgstr "名称"
+
+msgid "Name (optional)"
+msgstr "名称(可选)"
+
+msgid "Name accepted by AI · ready"
+msgstr "AI 命名已采纳 · 就绪"
+
+msgid "name matches"
+msgstr "名称匹配"
+
+msgid "Name, brand, serial or ID"
+msgstr "名称、品牌、序列号或 ID"
+
+msgid "Name, or its code"
+msgstr "名称或其编码"
+
+msgid "Names are matched ignoring case, accents and Arabic letter forms, so it wasn't added twice."
+msgstr "名称匹配时不区分大小写、重音符号和阿拉伯字母写法,因此不会重复添加。"
+
+msgid "Naming…"
+msgstr "正在命名…"
+
+msgid "Nearby · tap to change"
+msgstr "附近位置 · 轻点切换"
+
+msgid "Needs {needs}"
+msgstr "需要 {needs}"
+
+msgid "Needs {needs} · off in this location"
+msgstr "需要 {needs} · 此空间未开启"
+
+msgid "Needs a connection"
+msgstr "需要网络连接"
+
+msgid "Needs a connection. The rest were taken back."
+msgstr "需要联网,其余物品已标记收回。"
+
+msgid "Needs a connection. Try again when you're back online."
+msgstr "需要网络连接,请在恢复联网后重试。"
+
+msgid "Needs a currency"
+msgstr "需要选择币种"
+
+msgid "Needs a name"
+msgstr "需要填写名称"
+
+msgid "Needs a name: press E, or Edit, to type one."
+msgstr "需要名称:按 E 键或点击“编辑”输入名称。"
+
+msgid "Needs a name: tap Edit to type one."
+msgstr "需要名称:轻点“编辑”输入名称。"
+
+msgid "Needs email set up on this server"
+msgstr "需要在此服务器上配置邮件服务"
+
+msgid "Needs HTTPS first"
+msgstr "需要先启用 HTTPS"
+
+msgid "Needs review"
+msgstr "待审核"
+
+msgid "Needs you"
+msgstr "需要你处理"
+
+msgid "New"
+msgstr "新建"
+
+msgid "New {label}"
+msgstr "新建{label}"
+
+msgid "New box here"
+msgstr "在此新建箱子"
+
+msgid "New code"
+msgstr "生成新代码"
+
+msgid "New email address"
+msgstr "新邮箱地址"
+
+msgid "New kind"
+msgstr "新建类型"
+
+msgid "New location"
+msgstr "新建空间"
+
+msgid "New one-time code"
+msgstr "生成新的一次性登录码"
+
+msgid "New password"
+msgstr "新密码"
+
+msgid "New place kind"
+msgstr "新建位置类型"
+
+msgid "New type"
+msgstr "新建类型"
+
+msgid "Newest first"
+msgstr "最新优先"
+
+msgid "Next"
+msgstr "下一步"
+
+msgid "Next month"
+msgstr "下个月"
+
+msgid "Next photo"
+msgstr "下一张照片"
+
+msgid "Next time you sign in, Kept asks for a code from your app."
+msgstr "下次登录时,Kept 会要求输入验证器应用中的动态码。"
+
+msgid "no"
+msgstr "否"
+
+msgid "No"
+msgstr "否"
+
+msgid "No account yet? Ask someone who uses this Kept to invite you. The invite link creates your account."
+msgstr "还没有账号?请联系正在使用此 Kept 的人邀请你,打开邀请链接即可创建账号。"
+
+msgid "No activity matches"
+msgstr "没有匹配的活动记录"
+
+msgid "No backup configured"
+msgstr "未配置备份"
+
+msgid "No contact details yet."
+msgstr "暂无联系方式。"
+
+msgid "No currencies"
+msgstr "暂无币种"
+
+msgid "No end date"
+msgstr "无结束日期"
+
+msgid "No failed jobs"
+msgstr "没有失败的任务"
+
+msgid "No field groups."
+msgstr "暂无字段组。"
+
+msgid "No fields yet. Places of this kind have a name and what's in them."
+msgstr "暂无自定义字段。此类型的位置包含名称及其存放内容。"
+
+msgid "No fields yet. Things of this type have the usual name, photo and place."
+msgstr "暂无自定义字段。此类型的物品包含常规的名称、照片和位置。"
+
+msgid "No history yet"
+msgstr "暂无历史记录"
+
+msgid "No icon matches. Try another word, like \"box\" or \"tool\"."
+msgstr "没有匹配的图标。试试其他词,比如“box”或“tool”。"
+
+msgid "No links yet"
+msgstr "暂无链接"
+
+msgid "No match for ‘<0>{q}0>’"
+msgstr "未找到「<0>{q}0>」的匹配项"
+
+msgid "No matches"
+msgstr "无匹配项"
+
+msgid "No paperwork yet"
+msgstr "暂无单据"
+
+msgid "No pending invites"
+msgstr "暂无待处理邀请"
+
+msgid "No place kinds"
+msgstr "暂无位置类型"
+
+msgid "No place matches that."
+msgstr "没有符合条件的位置。"
+
+msgid "No price for this model, so every call says cost unknown"
+msgstr "未配置此模型的单价,因此每次调用都会显示费用未知"
+
+msgid "No readings yet"
+msgstr "暂无读数"
+
+msgid "No saved views yet. Filter the list, then save it to come back to it."
+msgstr "暂无保存的视图。先筛选列表,再保存视图以便随时回看。"
+
+msgid "No things use it in the locations you can see."
+msgstr "在你可见的空间中,没有任何物品使用此项。"
+
+msgid "No two-factor"
+msgstr "未启用双重验证"
+
+msgid "No two-factor yet, so {name} is hidden for them"
+msgstr "尚未设置双重验证,因此 {name} 对其不可见"
+
+msgid "No type"
+msgstr "无类型"
+
+msgid "No type matches."
+msgstr "没有匹配的类型。"
+
+msgid "No users yet"
+msgstr "暂无用户"
+
+msgid "None"
+msgstr "无"
+
+msgid "None of your locations is nearby."
+msgstr "附近没有你的空间。"
+
+msgid "None open"
+msgstr "暂无未结项"
+
+msgid "Not a duplicate · keep both"
+msgstr "不是重复项 · 两者都保留"
+
+msgid "Not a Kept label"
+msgstr "非 Kept 标签"
+
+msgid "Not answering"
+msgstr "无响应"
+
+msgid "Not available on this device."
+msgstr "在此设备上不可用。"
+
+msgid "Not configured"
+msgstr "未配置"
+
+msgid "Not done yet"
+msgstr "尚未完成"
+
+msgid "Not found in the product databases."
+msgstr "在商品数据库中未找到。"
+
+msgid "Not here"
+msgstr "不在此处"
+
+msgid "Not in your Kept"
+msgstr "不在你的 Kept 中"
+
+msgid "Not inside another type"
+msgstr "不嵌套在其他类型下"
+
+msgid "Not now"
+msgstr "暂不"
+
+msgid "Not on this phone"
+msgstr "不在此手机上"
+
+msgid "Not on this phone. Kept checks it when you open it online."
+msgstr "不在此手机上。联网打开时 Kept 会检查它。"
+
+msgid "Not recorded"
+msgstr "未记录"
+
+msgid "Not removed"
+msgstr "未移除"
+
+msgid "Not seen for a long time"
+msgstr "很久未见到"
+
+msgid "Not set"
+msgstr "未设置"
+
+msgid "Not shown to viewers here"
+msgstr "此处不对查看者显示"
+
+msgid "Not sure where"
+msgstr "不确定位置"
+
+msgid "Note"
+msgstr "备注"
+
+msgid "Note (optional)"
+msgstr "备注(可选)"
+
+msgid "Notes"
+msgstr "备注"
+
+msgid "Notes on ending"
+msgstr "结束备注"
+
+msgid "Nothing has happened yet"
+msgstr "暂无任何记录"
+
+msgid "Nothing here"
+msgstr "此处为空"
+
+msgid "Nothing here matches."
+msgstr "没有匹配的结果。"
+
+msgid "Nothing here yet"
+msgstr "这里还没有内容"
+
+msgid "Nothing in the locations you belong to has this label."
+msgstr "你所在的空间中没有使用此标签的物品。"
+
+msgid "Nothing in the tray. Pick things up from their menu, or scan them."
+msgstr "暂存区为空。可从物品菜单中拾取,或直接扫码加入。"
+
+msgid "Nothing is recorded in this box. Add what you find in it."
+msgstr "此箱子暂无物品记录。请添加你在箱中找到的物品。"
+
+msgid "Nothing matches these filters"
+msgstr "没有符合这些筛选条件的内容"
+
+msgid "Nothing matches. Try fewer words or clear a filter."
+msgstr "没有匹配结果。请尝试减少关键词或清除筛选条件。"
+
+msgid "Nothing moved. They're still in Unplaced."
+msgstr "未移动任何物品,它们仍留在「未放置」区域。"
+
+msgid "Nothing needs you"
+msgstr "暂无待处理事项"
+
+msgid "Nothing of yours waits. What you capture lands here when it needs you: a value to confirm, a receipt to link, a duplicate."
+msgstr "暂无待处理项。你采集的内容中需要确认数值、关联收据或疑似重复的部分会汇总于此。"
+
+msgid "Nothing on this phone matches ‘<0>{q}0>’"
+msgstr "此手机上没有匹配「<0>{q}0>」的内容"
+
+msgid "Nothing on this phone yet. Open Kept once while online to bring your places."
+msgstr "此手机上暂无离线数据。请在联网时打开一次 Kept 以同步你的位置。"
+
+msgid "Nothing recorded yet."
+msgstr "暂无记录。"
+
+msgid "Nothing to keep from that share"
+msgstr "此次分享中没有可保存的内容"
+
+msgid "Nothing waits for anyone. What AI can't settle lands here."
+msgstr "暂无待处理事项。AI 无法自动决定的内容会进入此处。"
+
+msgid "Nothing yet"
+msgstr "暂无内容"
+
+msgid "Notifications"
+msgstr "通知"
+
+msgid "Now check your new inbox"
+msgstr "请检查你的新邮箱收件箱"
+
+msgid "Number"
+msgstr "数字"
+
+msgid "Odometer"
+msgstr "里程表"
+
+msgid "of {total}"
+msgstr "共 {total}"
+
+msgid "Off"
+msgstr "关闭"
+
+msgid "Off by default. When on, the assistant can use it to answer you."
+msgstr "默认关闭。开启后,AI 助手可使用它来回答你的问题。"
+
+msgid "Off in this location"
+msgstr "在此空间中已关闭"
+
+msgid "Off is right for a household: people join through an invite, or you add them."
+msgstr "家庭使用建议关闭:成员通过邀请链接或由你手动添加加入。"
+
+msgid "Offered when you add a warranty for this brand."
+msgstr "为该品牌添加保修时会自动提供。"
+
+msgid "Office"
+msgstr "办公室"
+
+msgid "Offline"
+msgstr "离线"
+
+msgid "Offline · {queue}"
+msgstr "离线 · {queue}"
+
+msgid "Offline · as of last sync, {time}"
+msgstr "离线 · 上次同步于 {time}"
+
+msgid "Offline support (service worker)"
+msgstr "离线支持(Service Worker)"
+
+msgid "Offset"
+msgstr "偏移量"
+
+msgid "Old Homebox label"
+msgstr "旧版 Homebox 标签"
+
+msgid "Oldest first"
+msgstr "最旧优先"
+
+msgid "On"
+msgstr "已开启"
+
+msgid "On Home until every step is done."
+msgstr "在所有步骤完成前,会一直显示在主页。"
+
+msgid "On iPhone, Kept uploads only while it's open. Keep it open when you're back in signal."
+msgstr "在 iPhone 上,Kept 仅在前台打开时上传数据。恢复网络信号后请保持应用开启。"
+
+msgid "On iPhone, notifications only reach Kept once it's on your Home Screen. Until then, reminders can come by email."
+msgstr "在 iPhone 上,通知只有将 Kept 添加到主屏幕后才能送达。在此之前,提醒可通过邮件发送。"
+
+msgid "On iPhone, reminders only reach the installed app."
+msgstr "在 iPhone 上,提醒仅能推送到已安装的主屏幕应用。"
+
+msgid "On once an AI provider is connected. Turn off to keep {name} out of AI."
+msgstr "连接 AI 服务商后即开启。关闭此项可避免将 {name} 的数据发送给 AI。"
+
+msgid "On the receipt"
+msgstr "在收据上"
+
+msgid "On this phone"
+msgstr "在此手机上"
+
+msgid "On this phone · as of last sync, {time}"
+msgstr "在此手机上 · 上次同步于 {time}"
+
+msgid "On this phone · waiting to sync"
+msgstr "保存在此手机上 · 等待同步"
+
+msgid "On this phone; it syncs when you're online."
+msgstr "保存在此手机上;联网后将自动同步。"
+
+msgid "On your phone"
+msgstr "在你的手机上"
+
+msgid "On: a location uses it"
+msgstr "已开启:有空间正在使用"
+
+msgid "On. Signing in asks for a code from your authenticator app."
+msgstr "已开启。登录时需输入验证器应用中的动态码。"
+
+msgid "Once Kept is installed it's in the Share sheet. Share photos or PDFs to it from any app, and they open in Capture."
+msgstr "安装 Kept 后,它会出现在系统分享菜单中。从任意应用将照片或 PDF 分享到 Kept,即可直接在“采集”中打开。"
+
+msgid "One at a time with the move picker, or use Select below to move several at once."
+msgstr "可用移动选择器逐个移动,或点击下方的「选择」一次性移动多个。"
+
+msgid "One choice"
+msgstr "单选"
+
+msgid "One fewer"
+msgstr "减少 1 个"
+
+msgid "One more"
+msgstr "再来一个"
+
+msgid "One of a kind, with a serial number: always quantity 1."
+msgstr "独立单件,带序列号:数量始终为 1。"
+
+msgid "One use. Works for 7 days, until {expires}."
+msgstr "单次有效,有效期 7 天,至 {expires} 止。"
+
+msgid "One-time code"
+msgstr "一次性登录码"
+
+msgid "Online shop"
+msgstr "网店"
+
+msgid "Only {0}"
+msgstr "仅限 {0}"
+
+msgid "Only {0} goes to the trash."
+msgstr "仅将 {0} 移入回收站。"
+
+msgid "Only a type nothing uses can be deleted. To move its things to another type, merge it instead."
+msgstr "仅未被引用的类型可以删除。若要将其下物品迁至其他类型,请改用合并功能。"
+
+msgid "Only admins of every location that uses <0>{name}0> see these, and never offline."
+msgstr "只有使用了 <0>{name}0> 的所有空间的管理员才能查看这些内容,且离线不可见。"
+
+msgid "Only me"
+msgstr "仅自己"
+
+msgid "Only part of your Kept is on this phone."
+msgstr "仅部分 Kept 数据离线保存在此手机上。"
+
+msgid "Only say yes once the two keys from kept admin recovery-kit are stored away from this server. Kept can't check."
+msgstr "请仅在通过 kept admin recovery-kit 导出的两份密钥已安全存放在本服务器之外的地点后再选「是」。Kept 无法自行核验。"
+
+msgid "Only something nothing uses can be deleted. Otherwise, merge it into another."
+msgstr "只有未被任何项目使用的内容才能删除。否则请将其合并到其他项目。"
+
+msgid "Only the owner and admins add and change brands."
+msgstr "仅所有者和管理员可添加与修改品牌。"
+
+msgid "Only the owner and admins change these. You can look them up here."
+msgstr "仅所有者和管理员可更改这些设置,你可在此查看。"
+
+msgid "Only the owner and admins change this"
+msgstr "仅所有者和管理员可更改此项"
+
+msgid "Only the owner and admins change types. You can see how they're set up."
+msgstr "只有所有者和管理员可以修改类型。你可以查看当前配置。"
+
+msgid "Only the owner changes admins"
+msgstr "只有所有者可以变更管理员"
+
+msgid "Only the owner of {who}’s home location, or whoever created the account while still an admin there, can give {who} a new code."
+msgstr "只有 {who} 所属空间的所有者,或创建该账号且目前仍担任该空间管理员的成员,才能为 {who} 生成新的重置码。"
+
+msgid "Only the owner of a location sets its secret policies."
+msgstr "只有空间的拥有者才能设置其私密策略。"
+
+msgid "Only this"
+msgstr "仅此一项"
+
+msgid "Only you"
+msgstr "仅限你本人"
+
+msgid "Only you · nothing yet · captures with no location land here"
+msgstr "仅你可见 · 暂无内容 · 未指定空间的采集内容会落入此处"
+
+msgid "Only you see these. Restore one to bring it back with everything in it and everyone who had access."
+msgstr "只有你能看到这些项目。还原后,其中的所有内容及原有成员权限都会一并恢复。"
+
+msgid "open"
+msgstr "打开"
+
+msgid "Open"
+msgstr "打开"
+
+msgctxt "claim status"
+msgid "Open"
+msgstr "打开"
+
+msgctxt "map: go into the room"
+msgid "Open"
+msgstr "打开"
+
+msgid "Open {name}"
+msgstr "打开 {name}"
+
+msgid "Open {name} first here"
+msgstr "请先在此处打开 {name}"
+
+msgid "Open {title}"
+msgstr "打开 {title}"
+
+msgid "Open it"
+msgstr "打开"
+
+msgid "Open Kept"
+msgstr "打开 Kept"
+
+msgid "Open Kept from its new icon."
+msgstr "从新图标打开 Kept。"
+
+msgid "Open Kept once, then share again"
+msgstr "先打开一次 Kept,然后再尝试分享"
+
+msgid "Open that box"
+msgstr "打开该箱子"
+
+msgid "Open that place"
+msgstr "打开该位置"
+
+msgid "Open the browser's menu (the three dots)."
+msgstr "打开浏览器菜单(三个点图标)。"
+
+msgid "Open the invite link they sent you, or scan its QR code with this phone's camera."
+msgstr "打开对方发送给你的邀请链接,或用手机摄像头扫描其二维码。"
+
+msgid "Open the link on this device. Nothing arrived? Check spam, or ask your admin whether email is set up."
+msgstr "请在此设备上打开链接。没收到邮件?请检查垃圾邮件箱,或向管理员确认是否已配置邮件服务。"
+
+msgid "Open this box once while online, then you can check it offline too."
+msgstr "请在联网时先打开一次此收纳箱,之后即可离线查看与盘点。"
+
+msgid "Open this list with it"
+msgstr "用它打开此列表"
+
+msgid "Open to finish syncing ({waiting})"
+msgstr "打开以完成同步({waiting})"
+
+msgid "Open. New accounts get only their Personal location."
+msgstr "已开放。新账号仅会获得其「个人空间」。"
+
+msgid "Opened as the installed app"
+msgstr "以已安装应用打开"
+
+msgid "Opening the camera"
+msgstr "正在打开相机"
+
+msgid "Opening this phone's copy of your Kept…"
+msgstr "正在打开此手机上的 Kept 离线副本…"
+
+msgid "Optional: without one it waits in the Inbox to be named."
+msgstr "可选:不填则会留在收件箱等待命名。"
+
+msgid "or"
+msgstr "或"
+
+msgid "Or reach Kept through Tailscale and turn on HTTPS for your tailnet; the address ends in <0>.ts.net0>."
+msgstr "或者通过 Tailscale 访问 Kept 并为你的 tailnet 开启 HTTPS;地址以 <0>.ts.net0> 结尾。"
+
+msgid "Or search"
+msgstr "或搜索"
+
+msgid "Order"
+msgstr "顺序"
+
+msgid "Original file deleted"
+msgstr "原文件已删除"
+
+msgid "Other"
+msgstr "其他"
+
+msgctxt "incident kind"
+msgid "Other"
+msgstr "其他"
+
+msgid "Over plain HTTP, phones block the camera, installing Kept, push notifications and location."
+msgstr "在纯 HTTP 环境下,手机会禁用摄像头、安装 Kept、推送通知及定位功能。"
+
+msgid "Over plain HTTP, phones won't install Kept. Put Kept on HTTPS first."
+msgstr "在普通 HTTP 下,手机无法安装 Kept。请先为 Kept 启用 HTTPS。"
+
+msgid "Owner"
+msgstr "所有者"
+
+msgid "owns {n}"
+msgstr "拥有 {n} 项"
+
+msgid "Owns {name}"
+msgstr "拥有 {name}"
+
+msgid "Owns this location and decides who runs it."
+msgstr "拥有此空间,并决定谁可以管理它。"
+
+msgid "Page {0}"
+msgstr "第 {0} 页"
+
+msgid "Pages"
+msgstr "页数"
+
+msgid "paid by <0>{payer}0>"
+msgstr "由 <0>{payer}0> 支付"
+
+msgid "Paperwork"
+msgstr "文档与单据"
+
+msgid "Passkey sign-in was cancelled."
+msgstr "已取消通行密钥登录。"
+
+msgid "Password"
+msgstr "密码"
+
+msgid "Password changed"
+msgstr "密码已更改"
+
+msgid "Passwords and codes"
+msgstr "密码与验证码"
+
+msgid "Path"
+msgstr "路径"
+
+msgid "Paused by hand"
+msgstr "已手动暂停"
+
+msgid "Pending invites"
+msgstr "待处理邀请"
+
+msgid "People"
+msgstr "联系人"
+
+msgid "person"
+msgstr "人员"
+
+msgid "Person"
+msgstr "人员"
+
+msgid "Person added"
+msgstr "已添加联系人"
+
+msgid "Person changed"
+msgstr "人员已更改"
+
+msgid "Person deleted"
+msgstr "联系人已删除"
+
+msgid "Person merged"
+msgstr "已合并联系人"
+
+msgid "Personal"
+msgstr "个人空间"
+
+msgid "Personal AI key"
+msgstr "个人 AI 密钥"
+
+msgid "Phone"
+msgstr "电话"
+
+msgctxt "map shape"
+msgid "Phone"
+msgstr "手机"
+
+msgid "Photo"
+msgstr "照片"
+
+msgid "Photo {0} of {1}"
+msgstr "第 {0} 张照片,共 {1} 张"
+
+msgid "photos"
+msgstr "照片"
+
+msgid "Photos"
+msgstr "照片"
+
+msgid "Photos of what's in {name}"
+msgstr "{name} 内物品的照片"
+
+msgid "Photos still save; naming waits."
+msgstr "照片仍会自动保存,稍后再命名即可。"
+
+msgid "Pick a field group"
+msgstr "选择字段组"
+
+msgid "Pick a kind"
+msgstr "选择类型"
+
+msgid "Pick a type"
+msgstr "选择类型"
+
+msgid "Pick it up"
+msgstr "取走"
+
+msgid "Pick it up instead"
+msgstr "改为在店自提"
+
+msgid "Pick things up first, then scan where they go."
+msgstr "先拿起物品,再扫描它们要放入的位置。"
+
+msgid "Pick up"
+msgstr "拾取"
+
+msgid "Pick what you're capturing"
+msgstr "选择你要录入的内容"
+
+msgid "Picked up {0}"
+msgstr "已拿起 {0}"
+
+msgid "Pin {name}"
+msgstr "固定 {name}"
+
+msgid "Pin it as a tab above the list"
+msgstr "固定为列表上方的标签页"
+
+msgid "Pinned views"
+msgstr "置顶视图"
+
+msgid "Place"
+msgstr "位置"
+
+msgid "Place kind added"
+msgstr "已添加位置类型"
+
+msgid "Place kind changed"
+msgstr "位置类型已更改"
+
+msgid "Place kind customised"
+msgstr "已自定义位置类型"
+
+msgid "Place kinds"
+msgstr "位置类型"
+
+msgid "Places"
+msgstr "位置"
+
+msgid "Places · <0>{placeCount}0>"
+msgstr "位置 · <0>{placeCount}0>"
+
+msgid "Point at a Kept label"
+msgstr "对准 Kept 标签"
+
+msgid "Point at a Kept label, or a product's barcode."
+msgstr "对准 Kept 标签,或商品条形码。"
+
+msgid "Point at the label of the place or box they go in."
+msgstr "将镜头对准物品要放入的位置或箱子上的标签。"
+
+msgid "Policy"
+msgstr "策略"
+
+msgid "Policy {0}"
+msgstr "保单 {0}"
+
+msgid "Policy saved"
+msgstr "保单已保存"
+
+msgid "Poor"
+msgstr "较差"
+
+msgid "Preset for {name}"
+msgstr "适用于 {name} 的预设"
+
+msgid "preview unavailable"
+msgstr "无法预览"
+
+msgid "Preview unavailable"
+msgstr "无法预览"
+
+msgid "Previous"
+msgstr "上一项"
+
+msgid "Previous month"
+msgstr "上个月"
+
+msgid "Previous photo"
+msgstr "上一张照片"
+
+msgid "price"
+msgstr "价格"
+
+msgid "Price"
+msgstr "价格"
+
+msgid "Price hidden here"
+msgstr "此处已隐藏价格"
+
+msgid "Price saved"
+msgstr "价格已保存"
+
+msgid "Price when it ended"
+msgstr "终止时价格"
+
+msgid "Prices hidden"
+msgstr "价格已隐藏"
+
+msgid "Primitives"
+msgstr "基础元素"
+
+msgid "Print again"
+msgstr "重新打印"
+
+msgid "Print inventory"
+msgstr "打印清单"
+
+msgid "Print page sizes"
+msgstr "打印页面尺寸"
+
+msgid "Print your first label"
+msgstr "打印你的第一张标签"
+
+msgid "Printed a label"
+msgstr "已打印标签"
+
+msgid "Product barcode"
+msgstr "商品条形码"
+
+msgid "Proof"
+msgstr "凭证"
+
+msgid "purchase"
+msgstr "购买记录"
+
+msgid "Purchase"
+msgstr "采购记录"
+
+msgid "Purchase (optional)"
+msgstr "购买记录(可选)"
+
+msgid "Purchase added"
+msgstr "已添加购买记录"
+
+msgid "Purchase changed"
+msgstr "购买记录已更改"
+
+msgid "purchase date"
+msgstr "购买日期"
+
+msgid "Purchase deleted"
+msgstr "已删除采购记录"
+
+msgid "Purchase line added"
+msgstr "已添加采购明细"
+
+msgid "Purchase line changed"
+msgstr "购买明细已更改"
+
+msgid "Purchase line deleted"
+msgstr "已删除购买明细"
+
+msgid "Put it inside another place in {locationName}"
+msgstr "放入 {locationName} 中的另一个位置"
+
+msgid "Put Kept on HTTPS"
+msgstr "为 Kept 启用 HTTPS"
+
+msgid "Put them back"
+msgstr "放回原处"
+
+msgid "QR code for the invite link"
+msgstr "邀请链接二维码"
+
+msgid "QR code for your authenticator app"
+msgstr "供身份验证器应用扫描的二维码"
+
+msgid "QR codes"
+msgstr "二维码"
+
+msgid "quantity"
+msgstr "数量"
+
+msgid "Quantity"
+msgstr "数量"
+
+msgid "Queued again"
+msgstr "已重新加入队列"
+
+msgid "Re-type"
+msgstr "重新输入"
+
+msgid "reading"
+msgstr "读数"
+
+msgid "Reading"
+msgstr "读数"
+
+msgid "Reading ({0})"
+msgstr "读数({0})"
+
+msgid "Reading ({unit})"
+msgstr "读数({unit})"
+
+msgid "Reading changed"
+msgstr "读数已更改"
+
+msgid "Reading discarded"
+msgstr "已放弃读数"
+
+msgid "Reading doesn't fit"
+msgstr "读数不符合预期"
+
+msgid "Reading kept"
+msgstr "已保留读数"
+
+msgid "Reading logged"
+msgstr "读数已记录"
+
+msgid "Reading the photo again"
+msgstr "正在重新识别照片"
+
+msgid "Reading updated"
+msgstr "读数已更新"
+
+msgid "Readings"
+msgstr "读数"
+
+msgid "Readings around it"
+msgstr "相邻读数"
+
+msgid "Readings of {0}"
+msgstr "{0} 的读数"
+
+msgid "Readings to review"
+msgstr "待审核读数"
+
+msgid "Reads receipts and suggests details for you to confirm."
+msgstr "读取收据内容并自动建议详情,供你确认。"
+
+msgid "Ready to look up"
+msgstr "可立即查询"
+
+msgid "Receipt"
+msgstr "收据"
+
+msgid "Receipt {0}"
+msgstr "收据 {0}"
+
+msgid "Receipts"
+msgstr "收据"
+
+msgid "Receipts and warranties"
+msgstr "收据与保修"
+
+msgid "Receipts, manuals and warranty cards live here, as the originals."
+msgstr "收据、说明书和保修卡的原件均存放在这里。"
+
+msgid "Recent"
+msgstr "最近"
+
+msgid "Recent activity"
+msgstr "近期动态"
+
+msgid "Recent searches"
+msgstr "最近搜索"
+
+msgid "Recently deleted"
+msgstr "最近删除"
+
+msgid "Record the new meter"
+msgstr "记录新表计"
+
+msgid "Recorded the new meter"
+msgstr "已记录新表计"
+
+msgid "Recovery kit"
+msgstr "恢复工具包"
+
+msgid "Recovery kit noted as kept"
+msgstr "已标记为妥善保存恢复工具包"
+
+msgid "Registration"
+msgstr "注册"
+
+msgid "Reject"
+msgstr "拒绝"
+
+msgid "Reject the suggested value"
+msgstr "拒绝建议值"
+
+msgid "Related to"
+msgstr "关联至"
+
+msgid "Reload"
+msgstr "重新加载"
+
+msgid "Remind before expiry"
+msgstr "到期前提醒"
+
+msgid "Reminders"
+msgstr "提醒"
+
+msgid "Reminders need the installed app"
+msgstr "提醒功能需要安装应用"
+
+msgid "Remove"
+msgstr "移除"
+
+msgid "Remove {roomName}"
+msgstr "移除 {roomName}"
+
+msgid "Remove {who} as admin"
+msgstr "取消 {who} 的管理员身份"
+
+msgid "Remove {who} as an instance admin?"
+msgstr "确定撤销 {who} 的实例管理员权限?"
+
+msgid "Remove {who} from {place}?"
+msgstr "要将 {who} 从 {place} 移除吗?"
+
+msgid "Remove as admin"
+msgstr "取消管理员身份"
+
+msgid "Remove member…"
+msgstr "移除成员…"
+
+msgid "Remove Selina from this home?"
+msgstr "确定将 Selina 从此家庭中移除?"
+
+msgid "Remove the {gname} group"
+msgstr "移除 {gname} 分组"
+
+msgid "Remove the {label} filter"
+msgstr "移除「{label}」筛选条件"
+
+msgid "Remove the link to {0}"
+msgstr "移除与 {0} 的关联"
+
+msgid "Remove the photo"
+msgstr "移除照片"
+
+msgid "Remove this {0}"
+msgstr "移除此{0}"
+
+msgid "Remove this {0}?"
+msgstr "移除此{0}?"
+
+msgid "Removed"
+msgstr "已移除"
+
+msgid "Removed a file from {name}"
+msgstr "从 {name} 移除了一个文件"
+
+msgid "Removed with it"
+msgstr "随之移除"
+
+msgid "Rename"
+msgstr "重命名"
+
+msgid "Rename {current}"
+msgstr "重命名 {current}"
+
+msgid "Rename this thing"
+msgstr "重命名此物品"
+
+msgid "Rename…"
+msgstr "重命名…"
+
+msgid "Renamed"
+msgstr "已重命名"
+
+msgid "repeatable"
+msgstr "可重复"
+
+msgid "Replace"
+msgstr "替换"
+
+msgid "Replaced by"
+msgstr "已替换为"
+
+msgid "Replaces"
+msgstr "替代旧物品"
+
+msgid "Required"
+msgstr "必填"
+
+msgid "Reset links work once, for an hour. Ask for a new one on the sign-in page."
+msgstr "重置链接仅限使用一次,有效期 1 小时。请在登录页面重新申请。"
+
+msgid "Reset two-factor"
+msgstr "重置双重验证"
+
+msgid "Reset two-factor for {who}?"
+msgstr "为 {who} 重置双重验证?"
+
+msgid "Resolved"
+msgstr "已解决"
+
+msgctxt "claim status"
+msgid "Resolved"
+msgstr "已解决"
+
+msgid "Resolved {resolvedAt}"
+msgstr "已于 {resolvedAt} 解决"
+
+msgid "Restore"
+msgstr "恢复"
+
+msgid "Restore {0}"
+msgstr "恢复 {0}"
+
+msgid "Restore {entity}"
+msgstr "恢复 {entity}"
+
+msgid "Restore {name}"
+msgstr "恢复 {name}"
+
+msgid "Restored {name}"
+msgstr "已恢复 {name}"
+
+msgid "Restored, and the change applied"
+msgstr "已恢复,并应用了更改"
+
+msgid "Restored, but the change still couldn't apply"
+msgstr "已恢复,但仍无法应用该变更"
+
+msgid "Restored; the change waits in the inbox"
+msgstr "已恢复;该变更正在收件箱中等待处理"
+
+msgid "Results"
+msgstr "结果"
+
+msgid "Retry"
+msgstr "重试"
+
+msgid "Returned to its owner"
+msgstr "已归还给物主"
+
+msgid "Reveal"
+msgstr "显示"
+
+msgid "Reveal: owner and admins by default · AI: not allowed"
+msgstr "显示权限:默认仅所有者和管理员 · AI 访问:禁止"
+
+msgid "Revealed · logged"
+msgstr "已查看 · 已记入日志"
+
+msgid "Review"
+msgstr "审核"
+
+msgid "Review and save"
+msgstr "核对并保存"
+
+msgid "Reviewing needs a connection. What's here is as it was when you went offline."
+msgstr "审核需要网络连接。当前显示的是你离线前的快照。"
+
+msgid "Revoke"
+msgstr "撤销"
+
+msgid "Revoke this invite?"
+msgstr "要撤销此邀请吗?"
+
+msgid "Role"
+msgstr "角色"
+
+msgid "Room"
+msgstr "房间"
+
+msgid "Room or spot"
+msgstr "房间或点位"
+
+msgid "Room or spot {n}"
+msgstr "房间或点位 {n}"
+
+msgid "Room, spot or box"
+msgstr "房间、点位或箱子"
+
+msgid "Rooms"
+msgstr "房间"
+
+msgid "Rooms and spots come from its template; change them any time."
+msgstr "房间与点位均来自其模板,随时可以调整。"
+
+msgid "Rooms in {name}"
+msgstr "{name} 中的房间"
+
+msgid "Run the checks"
+msgstr "运行检查"
+
+msgid "Run the checks again"
+msgstr "重新运行检查"
+
+msgid "Same brand and model in the same place. Merging keeps both histories."
+msgstr "同一位置中品牌和型号均相同的物品。合并后将保留双方的历史记录。"
+
+msgid "same location"
+msgstr "同一空间"
+
+msgid "Same serial number. Merging keeps both histories."
+msgstr "序列号相同。合并后将保留双方的历史记录。"
+
+msgid "Sample things"
+msgstr "示例物品"
+
+msgid "Save"
+msgstr "保存"
+
+msgid "Save as new"
+msgstr "另存为新视图"
+
+msgid "Save changes"
+msgstr "保存更改"
+
+msgid "Save changes to {name}?"
+msgstr "保存对 {name} 的更改?"
+
+msgid "Save view"
+msgstr "保存视图"
+
+msgid "Saved"
+msgstr "已保存"
+
+msgid "Saved {n}"
+msgstr "已保存 {n}"
+
+msgid "Saved {name}"
+msgstr "已保存 {name}"
+
+msgid "Saved {saved}"
+msgstr "已保存 {saved}"
+
+msgid "Saved {trimmed}"
+msgstr "已保存 {trimmed}"
+
+msgid "Saved for review"
+msgstr "已保存待核对"
+
+msgid "Saved on this phone. It syncs when you're online."
+msgstr "已暂存于此手机,联网后将自动同步。"
+
+msgid "Saved searches"
+msgstr "已保存的搜索"
+
+msgid "Saved view added"
+msgstr "已添加保存视图"
+
+msgid "Saved view changed"
+msgstr "已保存视图已更改"
+
+msgid "Saved view deleted"
+msgstr "已删除保存的视图"
+
+msgid "Saved views"
+msgstr "已保存的视图"
+
+msgid "Saved, but the photo didn't upload"
+msgstr "已保存,但照片未上传成功"
+
+msgid "Saved. Preview unavailable"
+msgstr "已保存,预览不可用"
+
+msgid "Saving on this device"
+msgstr "正在保存到此设备"
+
+msgid "Saving shows what it changes first: the things affected in each location, and the types below it."
+msgstr "保存前会先展示影响范围:各空间内受影响的物品,以及继承此类型的子类型。"
+
+msgid "Saw {name}"
+msgstr "见到了 {name}"
+
+msgid "Scan"
+msgstr "扫码"
+
+msgid "Scan again"
+msgstr "重新扫码"
+
+msgid "Scan destination"
+msgstr "扫描目标位置"
+
+msgid "Scan its label"
+msgstr "扫描其标签"
+
+msgid "Scan result"
+msgstr "扫码结果"
+
+msgid "Scan something else"
+msgstr "扫描其他内容"
+
+msgid "Scan a label"
+msgstr "扫描标签"
+
+msgid "Scan this with your authenticator app, then type the code it shows."
+msgstr "使用身份验证器应用扫描此二维码,然后输入显示的验证码。"
+
+msgid "Scan to pick up"
+msgstr "扫码拾取"
+
+msgid "Scan with their phone"
+msgstr "用他们的手机扫码"
+
+msgid "Schedules"
+msgstr "计划"
+
+msgid "Scroll the list and tap <0>Add to Home Screen0>."
+msgstr "向下滚动列表并轻点<0>添加到主屏幕0>。"
+
+msgid "Search"
+msgstr "搜索"
+
+msgid "Search {label}"
+msgstr "搜索 {label}"
+
+msgid "Search {name}"
+msgstr "搜索 {name}"
+
+msgid "Search activity"
+msgstr "搜索动态"
+
+msgid "Search brands"
+msgstr "搜索品牌"
+
+msgid "Search by code or name"
+msgstr "按编码或名称搜索"
+
+msgid "Search by name"
+msgstr "按名称搜索"
+
+msgid "Search by name, a name it's also called, its brand, model or serial, or the 6-character ID on its label, in English or Arabic. Filters narrow it to a place, a type or a tag."
+msgstr "可按名称、别名、品牌、型号、序列号或标签上的 6 位 ID 搜索(支持英文或阿拉伯文)。使用筛选条件可按位置、类型或分类标签进一步缩小范围。"
+
+msgid "Search currencies"
+msgstr "搜索货币"
+
+msgid "Search everything"
+msgstr "搜索全部内容"
+
+msgid "Search for “{q}”"
+msgstr "搜索“{q}”"
+
+msgid "Search for it by name"
+msgstr "按名称搜索"
+
+msgid "Search icons"
+msgstr "搜索图标"
+
+msgid "Search icons: sofa, drill, box…"
+msgstr "搜索图标:沙发、电钻、箱子…"
+
+msgid "Search names, shops, places"
+msgstr "搜索名称、商店、位置"
+
+msgid "Search or filter the list first; a view keeps what you chose."
+msgstr "请先搜索或筛选列表;视图会保存你选择的条件。"
+
+msgid "Search or jump to"
+msgstr "搜索或跳转至"
+
+msgid "Search or jump to…"
+msgstr "搜索或跳转至…"
+
+msgid "Search people"
+msgstr "搜索人员"
+
+msgid "Search place kinds"
+msgstr "搜索位置类型"
+
+msgid "Search places"
+msgstr "搜索位置"
+
+msgid "Search rooms, spots and boxes"
+msgstr "搜索房间、点位和收纳箱"
+
+msgid "Search shops"
+msgstr "搜索商店"
+
+msgid "Search tags"
+msgstr "搜索分类标签"
+
+msgid "Search the inbox"
+msgstr "搜索收件箱"
+
+msgid "Search the trash"
+msgstr "搜索回收站"
+
+msgid "Search things here"
+msgstr "搜索此处物品"
+
+msgid "Search things, or jump to a place"
+msgstr "搜索物品,或跳转到位置"
+
+msgid "Search types"
+msgstr "搜索类型"
+
+msgid "Search vendors"
+msgstr "搜索商家"
+
+msgid "Searching…"
+msgstr "正在搜索…"
+
+msgid "Second bedroom"
+msgstr "次卧"
+
+msgid "Second floor"
+msgstr "二楼"
+
+msgid "Secret"
+msgstr "私密"
+
+msgid "Secret · you can't reveal this one"
+msgstr "加密 · 此字段不可明文查看"
+
+msgid "Secret changed"
+msgstr "密钥已更改"
+
+msgid "Secret cleared"
+msgstr "私密内容已清除"
+
+msgid "Secret copied"
+msgstr "已复制密钥"
+
+msgid "Secret policy changed"
+msgstr "私密策略已更改"
+
+msgid "Secret revealed"
+msgstr "已显示私密内容"
+
+msgid "secret text"
+msgstr "加密文本"
+
+msgid "Secret:"
+msgstr "密钥:"
+
+msgid "Sections"
+msgstr "分区"
+
+msgid "Secure connection (HTTPS)"
+msgstr "安全连接 (HTTPS)"
+
+msgid "Security"
+msgstr "安全"
+
+msgid "Seen {0}"
+msgstr "已见到:{0}"
+
+msgid "Seen just now"
+msgstr "刚刚见过"
+
+msgid "Select"
+msgstr "选择"
+
+msgid "Select {0}"
+msgstr "选择 {0}"
+
+msgid "Select {name}"
+msgstr "选择 {name}"
+
+msgid "Select drafts from one location to set a type, place or tags."
+msgstr "从同一空间中选择草稿,以批量设置类型、位置或分类标签。"
+
+msgid "Select the text and copy it by hand."
+msgstr "请选中文本并手动复制。"
+
+msgid "Selected drafts"
+msgstr "已选择的草稿"
+
+msgid "Selection"
+msgstr "已选内容"
+
+msgid "Send by email"
+msgstr "通过邮件发送"
+
+msgid "Send confirmation link"
+msgstr "发送确认链接"
+
+msgid "Sending"
+msgstr "正在发送"
+
+msgid "Separate several with commas."
+msgstr "多个项目请用英文逗号分隔。"
+
+msgid "Separate the choices with commas."
+msgstr "多个选项请用英文逗号分隔。"
+
+msgid "serial number"
+msgstr "序列号"
+
+msgid "Serial number"
+msgstr "序列号"
+
+msgid "Serialized"
+msgstr "按序列号管理"
+
+msgid "Service centre"
+msgstr "维修保养中心"
+
+msgid "Sessions and devices"
+msgstr "会话与设备"
+
+msgid "Set a value"
+msgstr "设置估值"
+
+msgid "Set by the environment"
+msgstr "由环境变量设定"
+
+msgid "Set password"
+msgstr "设置密码"
+
+msgid "Set password and sign in"
+msgstr "设置密码并登录"
+
+msgid "Set the currency to {currency}"
+msgstr "将币种设为 {currency}"
+
+msgid "Set the type of {names}"
+msgstr "设置 {names} 的类型"
+
+msgid "Set type"
+msgstr "设置类型"
+
+msgid "Set up"
+msgstr "设置"
+
+msgid "Set up this Kept"
+msgstr "配置此 Kept 实例"
+
+msgid "Setting it signs you out on every device."
+msgstr "设置后将退出其他所有设备的登录状态。"
+
+msgid "Settings"
+msgstr "设置"
+
+msgid "Setup code"
+msgstr "配置密钥"
+
+msgid "Several choices"
+msgstr "多个选项"
+
+msgid "Share a link or a QR code. Choose what they can do and for how long."
+msgstr "分享链接或二维码,并设置对方的权限范围与有效期限。"
+
+msgid "Share the files into Kept again."
+msgstr "请重新将文件分享到 Kept。"
+
+msgid "Share…"
+msgstr "分享…"
+
+msgid "Shared"
+msgstr "已共享"
+
+msgid "Shared files"
+msgstr "已分享的文件"
+
+msgid "Shared into Kept"
+msgstr "已分享到 Kept"
+
+msgid "Shared with {name}"
+msgstr "已与 {name} 共享"
+
+msgid "Shared with {name} · by {by}"
+msgstr "已分享给 {name} · 分享人:{by}"
+
+msgid "She will lose access straight away. Things she added stay."
+msgstr "她将立即失去访问权限,但她添加的物品仍会保留。"
+
+msgid "Shelves"
+msgstr "货架"
+
+msgid "shop"
+msgstr "商店"
+
+msgid "Shop"
+msgstr "商店"
+
+msgid "Shop (new)"
+msgstr "商店(新建)"
+
+msgid "Shop or service"
+msgstr "商店或服务商"
+
+msgid "Shops and services"
+msgstr "商店与服务商"
+
+msgid "Shops and services are added here, or while you record a purchase."
+msgstr "可在此处添加商店与服务商,或在记录购买时顺便添加。"
+
+msgid "Show"
+msgstr "显示"
+
+msgid "Show a toast"
+msgstr "显示轻提示"
+
+msgid "Show all"
+msgstr "显示全部"
+
+msgid "Show everything"
+msgstr "显示全部"
+
+msgid "Show password"
+msgstr "显示密码"
+
+msgid "Show steps"
+msgstr "显示步骤"
+
+msgid "Shown next to the number, never converted: in, cm, W."
+msgstr "显示在数值旁,不进行单位换算:in、cm、W。"
+
+msgid "Sign {who} out everywhere?"
+msgstr "将 {who} 从所有设备退出登录?"
+
+msgid "Sign in"
+msgstr "登录"
+
+msgid "Sign in as someone else"
+msgstr "切换账号登录"
+
+msgid "Sign in to Kept"
+msgstr "登录 Kept"
+
+msgid "Sign in with a one-time code"
+msgstr "使用一次性验证码登录"
+
+msgid "Sign in with a passkey"
+msgstr "使用通行密钥 (Passkey) 登录"
+
+msgid "Sign in with the new address from now on. Every other device was signed out, and your old address was told about the change."
+msgstr "之后请使用新邮箱地址登录。其他所有设备均已退出登录,我们也已向你的旧邮箱发送了变更通知。"
+
+msgid "Sign out"
+msgstr "退出登录"
+
+msgid "Sign out {title}?"
+msgstr "退出 {title} 的登录?"
+
+msgid "Sign out anyway"
+msgstr "仍然退出登录"
+
+msgid "Sign out everywhere"
+msgstr "退出所有设备"
+
+msgid "Sign out instead"
+msgstr "改为退出登录"
+
+msgid "Sign out of all other devices"
+msgstr "退出所有其他设备"
+
+msgid "Sign out of every other device?"
+msgstr "退出其他所有设备的登录?"
+
+msgid "Sign out others"
+msgstr "退出其他设备"
+
+msgid "Sign-in link sent. It works once, for 15 minutes."
+msgstr "登录链接已发送,15 分钟内单次有效。"
+
+msgid "Sign-in links work once, for 15 minutes. <0>Ask for a new one0>."
+msgstr "登录链接仅限使用一次,有效期 15 分钟。<0>重新获取链接0>。"
+
+msgid "Sign-up"
+msgstr "注册"
+
+msgid "Sign-up is closed on this server, and this invite is your way in. It works once."
+msgstr "此服务器已关闭公开注册,凭此邀请方可加入,且仅一次有效。"
+
+msgid "Signed in {since}"
+msgstr "登录于 {since}"
+
+msgid "Signed out {title}"
+msgstr "已退出 {title}"
+
+msgid "Signed out of your other devices"
+msgstr "已退出其他设备上的登录"
+
+msgid "Size"
+msgstr "尺寸"
+
+msgid "Skip"
+msgstr "跳过"
+
+msgid "Skip for now"
+msgstr "暂时跳过"
+
+msgid "Skip keeps only Unplaced. You can add rooms later from the location."
+msgstr "跳过将仅保留「未放置」区域。你之后可在空间中随时添加房间。"
+
+msgid "Skip this line"
+msgstr "跳过此行"
+
+msgid "Small"
+msgstr "小"
+
+msgid "So it can be carried, with what's in it, as one thing"
+msgstr "使其可连同内部物品作为整体搬运"
+
+msgid "Sold"
+msgstr "已售出"
+
+msgid "Sold for"
+msgstr "售出价格"
+
+msgid "Sold to"
+msgstr "售予"
+
+msgid "Some of that isn't valid. Check the fields and try again."
+msgstr "部分输入无效。请检查字段后重试。"
+
+msgid "Someone"
+msgstr "某人"
+
+msgid "Someone changed this {0} since you opened it. Close and open it again to see their change."
+msgstr "自你打开此{0}后,有人进行了修改。请关闭后重新打开以查看最新更改。"
+
+msgid "something"
+msgstr "某项内容"
+
+msgid "Something not working?"
+msgstr "遇到问题?"
+
+msgid "Something went wrong on the server. Try again in a moment."
+msgstr "服务器出现问题,请稍后再试。"
+
+msgid "Something went wrong on the server. Try again."
+msgstr "服务器出现错误,请重试。"
+
+msgid "Something went wrong. Try again."
+msgstr "出了点问题,请重试。"
+
+msgid "Sort"
+msgstr "排序"
+
+msgid "Sort them"
+msgstr "整理这些物品"
+
+msgid "Sort Unplaced"
+msgstr "整理未放置物品"
+
+msgid "Sort Unplaced · {n} of {total}"
+msgstr "整理未放置物品 · {n} / {total}"
+
+msgid "Source"
+msgstr "来源"
+
+msgid "Source code"
+msgstr "源代码"
+
+msgid "Spare part for"
+msgstr "备件适用于"
+
+msgid "Split"
+msgstr "拆分"
+
+msgid "Split {0}"
+msgstr "拆分 {0}"
+
+msgid "Split {0} off"
+msgstr "拆分出 {0}"
+
+msgid "Split {name}"
+msgstr "拆分 {name}"
+
+msgid "Spot"
+msgstr "点位"
+
+msgid "Start"
+msgstr "开始"
+
+msgid "Start Kept's Compose file with the <0>https0> profile. It adds a reverse proxy that gets a certificate for your domain."
+msgstr "使用 <0>https0> 配置集启动 Kept 的 Compose 文件,它会自动添加反向代理并为你的域名申请证书。"
+
+msgid "State"
+msgstr "状态"
+
+msgid "Status"
+msgstr "状态"
+
+msgid "Stay signed in and open Kept with a connection to finish syncing first."
+msgstr "请保持登录状态并联网打开 Kept,以先完成同步。"
+
+msgid "Step {step} of {steps}"
+msgstr "第 {step} 步,共 {steps} 步"
+
+msgid "Stick it on a box, then scan it to see what's inside."
+msgstr "贴在箱子上,扫码即可查看里面装了什么。"
+
+msgid "still a draft"
+msgstr "仍为草稿"
+
+msgid "Stolen"
+msgstr "被盗"
+
+msgid "Stop being an instance admin?"
+msgstr "卸任实例管理员?"
+
+msgid "Stop opening {name} first"
+msgstr "取消默认打开 {name}"
+
+msgid "Storage kept by the phone"
+msgstr "手机本地保留的存储空间"
+
+msgid "Storage room"
+msgstr "储藏室"
+
+msgid "Storage unit"
+msgstr "储物柜"
+
+msgid "Suggest where I am"
+msgstr "推荐我所在的位置"
+
+msgid "Suggested"
+msgstr "建议"
+
+msgid "Suggested · {fieldName}"
+msgstr "建议 · {fieldName}"
+
+msgid "Suggested · read from the receipt. Check it before you accept."
+msgstr "建议值 · 从收据中识别。采纳前请核对。"
+
+msgid "Suggested {fieldName}"
+msgstr "建议的{fieldName}"
+
+msgid "Suggested values wait for you"
+msgstr "建议估值待你确认"
+
+msgid "Support phone"
+msgstr "客服电话"
+
+msgid "Switch"
+msgstr "切换"
+
+msgid "Synced"
+msgstr "已同步"
+
+msgid "System"
+msgstr "系统"
+
+msgid "tag"
+msgstr "分类标签"
+
+msgid "Tag"
+msgstr "分类标签"
+
+msgid "Tag added"
+msgstr "已添加分类标签"
+
+msgid "Tag changed"
+msgstr "分类标签已更改"
+
+msgid "Tag deleted"
+msgstr "分类标签已删除"
+
+msgid "Tag merged"
+msgstr "分类标签已合并"
+
+msgid "tags"
+msgstr "分类标签"
+
+msgid "Tags"
+msgstr "分类标签"
+
+msgid "Tags are labels you filter and search by, like \"winter\" or \"kids\"."
+msgstr "分类标签用于筛选和搜索,例如“冬季”或“儿童”。"
+
+msgid "Take a photo"
+msgstr "拍照"
+
+msgid "Take a photo first"
+msgstr "请先拍一张照片"
+
+msgid "Take it out of the tray"
+msgstr "从待处理列表中移出"
+
+msgid "Take out of tray"
+msgstr "移出暂存区"
+
+msgid "Take photo: add to {name}"
+msgstr "拍照:添加到 {name}"
+
+msgid "Take photo: add to this thing"
+msgstr "拍照:添加到此物品"
+
+msgid "Take photo: another page of this receipt"
+msgstr "拍照:此收据的下一页"
+
+msgid "Take photo: label"
+msgstr "拍摄标签照片"
+
+msgid "Take photo: new thing"
+msgstr "拍照:新建物品"
+
+msgid "Take photo: reading"
+msgstr "拍照:表计读数"
+
+msgid "Take photo: receipt"
+msgstr "拍照:收据"
+
+msgid "Take them out, then trash it"
+msgstr "先取出物品,再移入回收站"
+
+msgid "Taken"
+msgstr "已借走"
+
+msgid "Tap <0>Add0>, then open Kept from its new icon."
+msgstr "轻点<0>添加0>,然后从新图标打开 Kept。"
+
+msgid "Tap <0>Install app0>, or <1>Add to Home screen1>."
+msgstr "轻点<0>安装应用0>,或<1>添加到主屏幕1>。"
+
+msgid "Tap <0>Share0> <1/> in Safari's toolbar."
+msgstr "轻点 Safari 工具栏中的<0>共享0> <1/>。"
+
+msgid "Tap to change"
+msgstr "轻点以更改"
+
+msgid "Tax"
+msgstr "税费"
+
+msgid "Templates"
+msgstr "模板"
+
+msgid "Text"
+msgstr "文本"
+
+msgid "Text fields"
+msgstr "文本字段"
+
+msgid "That account can't be made an admin now. Reload and try again."
+msgstr "目前无法将该账号设为管理员。请刷新后重试。"
+
+msgid "That backup code didn't work. Each one works only once."
+msgstr "该备用恢复码无效。每个恢复码仅可使用一次。"
+
+msgid "That change can't be undone"
+msgstr "该更改无法撤销"
+
+msgid "That code didn't match. Check the time on your phone, then try the newest code."
+msgstr "验证码不匹配。请核对手机系统时间后,再尝试最新的验证码。"
+
+msgid "That code didn't match. Try the newest one your app shows."
+msgstr "验证码不匹配。请尝试验证器应用显示的最新动态码。"
+
+msgid "That conflicts with a change someone else made. Reload and try again."
+msgstr "与其他人的修改冲突。请刷新后重试。"
+
+msgid "That didn't work"
+msgstr "操作未能成功"
+
+msgid "That doesn't look like an email address."
+msgstr "这不像是一个有效的邮箱地址。"
+
+msgid "That email or username and password don't match."
+msgstr "邮箱/用户名与密码不匹配。"
+
+msgid "That key is already a field of this type, one it inherits from, or one below it. Pick another key."
+msgstr "该键名已是此类型、其上级继承类型或下级子类型的字段。请另选一个键名。"
+
+msgid "That label isn't on a thing in your Kept."
+msgstr "该标签尚未绑定到你的 Kept 中的任何物品。"
+
+msgid "That name is already in this list. Merge the two instead."
+msgstr "此列表中已存在该名称,请改为合并两者。"
+
+msgid "That passkey couldn't confirm it's you. Use a code instead."
+msgstr "该通行密钥无法确认你的身份,请改用验证码。"
+
+msgid "That password isn't right."
+msgstr "密码不正确。"
+
+msgid "That setup code isn't right. Check the server's logs."
+msgstr "该设置码不正确,请检查服务器日志。"
+
+msgid "That share has expired"
+msgstr "该分享已过期"
+
+msgid "That username and code don't match, or the code has expired. Ask for a new one."
+msgstr "用户名与验证码不匹配,或验证码已过期。请重新获取。"
+
+msgid "That would give a field key twice: a group or parent already has a field this type defines. Remove the clash first."
+msgstr "这会导致字段键名重复:某个分组或父类型中已存在该类型定义的同名字段。请先解决冲突。"
+
+msgid "That would give the field “{clash}” twice: a group or parent already has it. Remove the clash first."
+msgstr "这会导致“{clash}”字段重复:分组或上级类型中已存在该字段。请先解决冲突。"
+
+msgid "That's already on the list."
+msgstr "该项已在列表中。"
+
+msgid "That's already your email address."
+msgstr "这已经是你当前的邮箱地址。"
+
+msgid "That's in another location. Move it from its own page."
+msgstr "该对象位于另一个空间中,请从其自身页面进行移动。"
+
+msgid "That's turned off in this location."
+msgstr "该功能在此空间中已关闭。"
+
+msgid "The 6 characters printed under the QR code."
+msgstr "印在二维码下方的 6 位字符。"
+
+msgid "The assistant may read it"
+msgstr "AI 助手可读取该字段"
+
+msgid "The camera needs a secure (HTTPS) address, and this page doesn't have one. Your admin can put Kept on HTTPS."
+msgstr "相机需要安全 (HTTPS) 地址,当前页面未使用 HTTPS。请联系管理员为 Kept 配置 HTTPS。"
+
+msgid "The code is 6 letters and digits, like K7Q-2M9."
+msgstr "编码由 6 位字母和数字组成,例如 K7Q-2M9。"
+
+msgid "The code is 8 characters."
+msgstr "代码应为 8 个字符。"
+
+msgid "The current item"
+msgstr "当前物品"
+
+msgid "The email-change link is missing its code. Open it straight from the email, or start again from Settings."
+msgstr "邮箱变更链接缺少验证码。请直接从邮件中打开链接,或从设置重新开始。"
+
+msgid "The first things in <0>{home}0> go where you choose. You can change it any time from the place at the top."
+msgstr "首批导入 <0>{home}0> 的物品将放入你指定的位置。你随时可在顶部切换目标位置。"
+
+msgid "The inbox is for members"
+msgstr "收件箱仅对成员开放"
+
+msgid "The key and kind stay as they are. Changing a kind comes with a preview, later."
+msgstr "字段键名与类型保持不变。如需更改类型,稍后会先显示预览。"
+
+msgid "The lines don't add up to the total (more than 1% apart). Check them."
+msgstr "各明细行之和与总金额不一致(偏差超过 1%),请核对。"
+
+msgid "The link is missing its code. Open it straight from the message, or scan the QR code again."
+msgstr "链接缺少验证码。请直接从消息中打开,或重新扫描二维码。"
+
+msgid "The link stops working. Anyone who hasn't opened it yet will need a new one."
+msgstr "原链接将立即失效,尚未打开的人需要获取新链接。"
+
+msgid "the location"
+msgstr "该空间"
+
+msgid "The lookup didn't answer. You can still add it."
+msgstr "查询服务未响应,你仍可手动添加。"
+
+msgid "The lowest is above the highest."
+msgstr "最低值高于最高值。"
+
+msgid "The monthly cap is reached"
+msgstr "已达到本月额度上限"
+
+msgid "The monthly token limit is reached"
+msgstr "已达到本月 token 限额"
+
+msgid "The old meter's last reading ({unit})"
+msgstr "旧表计末次读数({unit})"
+
+msgid "The one already in Kept, <0>{0}0>"
+msgstr "Kept 中已有的 <0>{0}0>"
+
+msgid "The original is kept. This format can't be previewed yet."
+msgstr "原文件已保留,暂不支持预览此格式。"
+
+msgid "The owner is told about every new managed account."
+msgstr "所有者会收到每个新建受管账号的通知。"
+
+msgid "The people who run this server manage users, sign-up and jobs here. Ask one of them if something needs changing."
+msgstr "本服务器的运维人员在此管理用户、注册和后台任务。如有需要调整的事项,请联系他们。"
+
+msgid "The price paid for one, as recorded on its purchase."
+msgstr "采购记录中登记的单个实付价格。"
+
+msgid "The recovery kit comes first"
+msgstr "请先备份恢复套件"
+
+msgid "The reset link is missing its code. Open it straight from the email, or ask for a new one on the sign-in page."
+msgstr "重置链接缺少验证码。请直接从邮件中打开链接,或在登录页重新申请。"
+
+msgid "The server couldn't apply it."
+msgstr "服务器无法应用此更改。"
+
+msgid "The server is busy making previews. Try again in a moment; nothing was lost."
+msgstr "服务器正在生成预览,请稍后再试;数据未丢失。"
+
+msgid "The sign-in link is missing its code. Open it straight from the email, or ask for a new one."
+msgstr "登录链接缺少验证码。请直接从邮件中打开,或申请新的登录链接。"
+
+msgid "The things it finds stay."
+msgstr "已找出的物品会保留下来。"
+
+msgid "The total is a number, like 5800.00."
+msgstr "总金额须为数字,例如 5800.00。"
+
+msgid "The trash is empty"
+msgstr "回收站为空"
+
+msgid "The tray stays with you, offline too."
+msgstr "暂存托盘会一直随行保存,离线时也一样。"
+
+msgid "Their access, and any tokens they make, stop on this date."
+msgstr "对方的访问权限以及创建的任何令牌都将在该日期失效。"
+
+msgid "Their access, and any tokens they make, stop on this date. It can't be later than your own, {capText}."
+msgstr "他们的访问权限及创建的任何令牌都将在此日期停止。不能晚于你自己的期限({capText})。"
+
+msgid "Their authenticator and backup codes stop working, and they set two-factor up again at their next sign-in. They get an email about it."
+msgstr "其身份验证器和备用恢复码将立即失效,下次登录时需重新设置双重验证。系统会向其发送邮件通知。"
+
+msgid "Their other changes are already in. For each field below, choose which version to keep."
+msgstr "对方的其他更改已合并完成。请为下方每个字段选择要保留的版本。"
+
+msgid "them"
+msgstr "它们"
+
+msgid "Theme"
+msgstr "主题"
+
+msgid "Then set KEPT_PUBLIC_URL to the https address and restart Kept."
+msgstr "然后将 KEPT_PUBLIC_URL 设为该 https 地址并重启 Kept。"
+
+msgid "There are {0}. The ones you take off get their own row, keeping the same purchase."
+msgstr "共有 {0}。拆出的部分会生成独立一行,并保留同一笔购买记录。"
+
+msgid "There's already a kind with that name."
+msgstr "已存在同名类型。"
+
+msgid "These fields leave the type. Their values are archived on each thing, not deleted, and come back if the field does:"
+msgstr "以下字段将从该类型中移除。它们在各物品上的已有值会被归档而不会删除,若重新添加字段则会恢复:"
+
+msgid "These things change type:"
+msgstr "以下物品将更改类型:"
+
+msgid "These values will be archived"
+msgstr "以下字段值将被归档"
+
+msgid "They go to the trash with their photos. You can restore them for 30 days."
+msgstr "它们及其照片将一同移入回收站,30 天内可随时恢复。"
+
+msgid "They stay on the thing under Archived fields, and come back if you re-type again."
+msgstr "它们会保留在物品的「已归档字段」下;如果重新改回该类型,字段值会自动恢复。"
+
+msgid "They're somewhere else"
+msgstr "它们在其他地方"
+
+msgid "Thing"
+msgstr "物品"
+
+msgid "Thing, receipt, label or reading. Switch any time; the camera stays open."
+msgstr "物品、收据、标签或读数。随时切换,相机保持开启。"
+
+msgid "Things"
+msgstr "物品"
+
+msgid "Things affected"
+msgstr "受影响的物品"
+
+msgid "Things by {name}"
+msgstr "{name} 下的物品"
+
+msgid "Things captured with no place yet"
+msgstr "已录入但暂未指定位置的物品"
+
+msgid "Things found"
+msgstr "找到的物品"
+
+msgid "Things in the same location, by brand and model or by name."
+msgstr "同一空间内的物品,按品牌与型号或按名称分组。"
+
+msgid "Things moved"
+msgstr "物品已移动"
+
+msgid "Things show here when a purchase from here is recorded for them."
+msgstr "当物品记录了来自此处的购买信息时,就会显示在这里。"
+
+msgid "Things show here when you set their brand."
+msgstr "为物品设置品牌后,它们会显示在这里。"
+
+msgid "Things show here when you set who they belong to, on the thing's page."
+msgstr "在物品页面设置归属人后,对应物品就会显示在这里。"
+
+msgid "Things with this label"
+msgstr "贴有此标签的物品"
+
+msgid "Things you run out of"
+msgstr "易耗物品"
+
+msgid "Things, vehicles and paperwork."
+msgstr "物品、车辆与单据文书。"
+
+msgid "This account runs the server: users, sign-up and backups. It can't see inside anyone's home unless they invite it."
+msgstr "此账号负责管理服务器:用户、注册和备份。除非受邀,否则无法查看任何人的空间内容。"
+
+msgid "This address doesn't lead to a page in Kept. The link may be old."
+msgstr "此地址未指向 Kept 中的任何页面。链接可能已失效。"
+
+msgid "This batch"
+msgstr "本批次"
+
+msgid "this box"
+msgstr "此箱子"
+
+msgid "This browser can't open the camera here."
+msgstr "当前浏览器无法在此处打开摄像头。"
+
+msgid "The scanner didn't start."
+msgstr "扫描器未能启动。"
+
+msgid "This browser may clear Kept's offline copy after weeks unused. Open Kept to sync soon."
+msgstr "如果数周未使用,此浏览器可能会清除 Kept 的离线副本。请尽快打开 Kept 进行同步。"
+
+msgid "This changed since you opened it. Reload and try again."
+msgstr "此内容在你打开后已被修改。请刷新后重试。"
+
+msgid "This code isn't one of Kept's labels. It says:"
+msgstr "此二维码不是 Kept 的标签。其内容为:"
+
+msgid "This device"
+msgstr "此设备"
+
+msgid "This device has no camera Kept can use."
+msgstr "此设备没有 Kept 可用的摄像头。"
+
+msgid "This device stays signed in. The others need your password or passkey again."
+msgstr "此设备会保持登录状态。其他设备需要重新使用密码或通行密钥登录。"
+
+msgid "This draft"
+msgstr "此草稿"
+
+msgid "This draft, <0>{name}0>"
+msgstr "此草稿,<0>{name}0>"
+
+msgid "This invite is for one email address: join with that address."
+msgstr "此邀请仅限特定邮箱使用:请使用该邮箱加入。"
+
+msgid "This invite link is incomplete"
+msgstr "此邀请链接不完整"
+
+msgid "This invite no longer works"
+msgstr "此邀请已失效"
+
+msgid "This invite no longer works."
+msgstr "此邀请已失效。"
+
+msgid "This invite no longer works. Ask {inviter} for a new one."
+msgstr "此邀请已失效,请向 {inviter} 索取新的邀请。"
+
+msgid "This isn't here any more, or you can't see it."
+msgstr "该内容已不存在,或你无权查看。"
+
+msgid "This Kept is already set up. Sign in instead."
+msgstr "此 Kept 实例已完成初始化设置,请直接登录。"
+
+msgid "This label isn't on anything yet. Use it for:"
+msgstr "此标签尚未绑定任何对象。可用于:"
+
+msgid "This label was claimed on another phone for “<0>{0}0>”."
+msgstr "此标签已在另一台手机上认领用于「<0>{0}0>」。"
+
+msgid "This label was claimed on another phone for <0>{name}0>. What you claimed it for keeps its pending ID; print it another label."
+msgstr "此标签已被另一台手机领用给 <0>{name}0>。你领用的对象会保留其待分配编号;请为它重新打印一张标签。"
+
+msgid "This link is incomplete"
+msgstr "此链接不完整"
+
+msgid "This link no longer works"
+msgstr "此链接已失效"
+
+msgid "This link no longer works. Links work once, and only for a while."
+msgstr "此链接已失效。链接仅限使用一次,且有时效限制。"
+
+msgid "This moves it to {target}"
+msgstr "这会将其移至 {target}"
+
+msgid "This needs a value."
+msgstr "此项需要填写内容。"
+
+msgid "This page is on plain HTTP"
+msgstr "此页面当前使用普通 HTTP"
+
+msgid "This PDF has expired"
+msgstr "此 PDF 已过期"
+
+msgid "This phone format can't be previewed yet. The original is kept."
+msgstr "此手机图片格式暂不支持预览,原图已保留。"
+
+msgid "This phone is out of space for Kept. Free some space to keep capturing offline."
+msgstr "此手机分配给 Kept 的存储空间已满。请清理一些空间以继续离线录入。"
+
+msgid "This phone may be out of space."
+msgstr "此手机存储空间可能不足。"
+
+msgid "This sign-in timed out. Start again from the sign-in page."
+msgstr "本次登录已超时。请从登录页重新开始。"
+
+msgid "This step ticks itself the first time you open Kept from its icon."
+msgstr "当你首次从桌面图标打开 Kept 时,此步骤会自动勾选完成。"
+
+msgid "This thing is…"
+msgstr "这件物品是…"
+
+msgid "This year"
+msgstr "今年"
+
+msgid "Three people can see this home."
+msgstr "三个人可以查看这个家。"
+
+msgid "Thrown away"
+msgstr "已丢弃"
+
+msgid "Ticked"
+msgstr "已勾选"
+
+msgid "Tips"
+msgstr "提示"
+
+msgid "to"
+msgstr "至"
+
+msgid "To come back, someone in {name} has to invite you again."
+msgstr "如需重新加入,必须由 {name} 中的成员再次邀请你。"
+
+msgid "To confirm: {list}"
+msgstr "待确认:{list}"
+
+msgid "Today"
+msgstr "今天"
+
+msgid "Today · {long}"
+msgstr "今天 · {long}"
+
+msgid "Today's AI budget is used up"
+msgstr "今日 AI 预算已用完"
+
+msgid "Too many attempts. Try again in {wait} seconds."
+msgstr "尝试次数过多,请在 {wait} 秒后重试。"
+
+msgid "Too many attempts. Wait a minute and try again."
+msgstr "尝试次数过多,请等待一分钟后再试。"
+
+msgid "Tool wall"
+msgstr "工具挂墙"
+
+msgid "Tools"
+msgstr "工具"
+
+msgctxt "sidebar group"
+msgid "Tools"
+msgstr "工具"
+
+msgid "Top level"
+msgstr "顶层"
+
+msgid "Total"
+msgstr "总计"
+
+msgid "Total <0>{0} {1}0>"
+msgstr "总计 <0>{0} {1}0>"
+
+msgid "Transfer is in Location settings"
+msgstr "所有权转让位于「空间设置」中"
+
+msgid "Trash"
+msgstr "回收站"
+
+msgid "Trash them too"
+msgstr "一并移入回收站"
+
+msgid "Trash them with it"
+msgstr "一并移入回收站"
+
+msgid "Trashed"
+msgstr "已移入回收站"
+
+msgid "Trashed {name}"
+msgstr "已将 {name} 移入回收站"
+
+msgid "Trashed {when}"
+msgstr "移入回收站于 {when}"
+
+msgid "Trashed {when} by <0>{by}0>"
+msgstr "由 <0>{by}0> 于 {when} 移入回收站"
+
+msgid "Trashed things and places wait here for 30 days, then go for good. Restore anything trashed by mistake."
+msgstr "移入回收站的物品和位置会在此保留 30 天,之后将永久删除。如有误删,可随时恢复。"
+
+msgid "Try again"
+msgstr "重试"
+
+msgid "Try fewer words, another spelling, or clear a filter."
+msgstr "请尝试减少关键词、更换拼写或清除筛选条件。"
+
+msgid "Try other words, another person, kind or date, or clear a filter."
+msgstr "请尝试其他关键词、人员、类型或日期,或清除筛选条件。"
+
+msgid "Turn {0} into a room or spot?"
+msgstr "要将 {0} 转为房间或点位吗?"
+
+msgid "Turn {name} into a box?"
+msgstr "将 {name} 转为箱子?"
+
+msgid "Turn into a box"
+msgstr "转为收纳箱"
+
+msgid "Turn on"
+msgstr "开启"
+
+msgid "Turn on two-factor"
+msgstr "开启双重验证"
+
+msgid "Turned {name} into a box"
+msgstr "已将 {name} 转为箱子"
+
+msgid "Turned {name} into a place"
+msgstr "已将 {name} 转为位置"
+
+msgid "Turned into"
+msgstr "已转换为"
+
+msgid "Turning something off hides it here. Nothing is deleted."
+msgstr "关闭某项功能只会将其在此处隐藏,不会删除任何数据。"
+
+msgid "Turns off: {offList}. Hidden, not deleted."
+msgstr "将关闭:{offList}。仅隐藏,不会删除。"
+
+msgid "Turns on: {onList}."
+msgstr "将开启:{onList}。"
+
+msgid "Two-factor"
+msgstr "双重验证"
+
+msgid "Two-factor is on"
+msgstr "已开启双重验证"
+
+msgid "two-factor required"
+msgstr "需要双重验证"
+
+msgid "Two-factor required"
+msgstr "需要双重验证"
+
+msgid "type"
+msgstr "类型"
+
+msgid "Type"
+msgstr "类型"
+
+msgid "Type a name first."
+msgstr "请先输入名称。"
+
+msgid "Type a name, or take a photo."
+msgstr "输入名称,或拍张照片。"
+
+msgid "Type added"
+msgstr "已添加类型"
+
+msgid "Type changed"
+msgstr "类型已更改"
+
+msgid "Type customised"
+msgstr "类型已自定义"
+
+msgid "Type deleted"
+msgstr "类型已删除"
+
+msgid "Type icons"
+msgstr "类型图标"
+
+msgid "Type merged"
+msgstr "类型已合并"
+
+msgid "Type the code"
+msgstr "输入验证码"
+
+msgid "Type the code printed under the QR code instead."
+msgstr "改为输入二维码下方印制的编码。"
+
+msgid "Type the shop's name."
+msgstr "输入商店名称。"
+
+msgid "Type to search. Never a native select."
+msgstr "输入以搜索,不使用浏览器原生下拉框。"
+
+msgid "Types"
+msgstr "类型"
+
+msgid "Types below it, which inherit the change"
+msgstr "将继承此更改的子类型"
+
+msgid "Types, place kinds and lists here are shared by every location in <0>{0}0>."
+msgstr "此处的物品类型、位置类型和列表由 <0>{0}0> 下的所有空间共享。"
+
+msgid "Types, place kinds and lists here are shared by every location you own."
+msgstr "这里的类型、位置类型与列表会在你拥有的所有空间之间共享。"
+
+msgid "Uncertain"
+msgstr "不确定"
+
+msgid "Undid a change to {name}"
+msgstr "已撤销对 {name} 的更改"
+
+msgid "Undo"
+msgstr "撤销"
+
+msgid "Undo changes"
+msgstr "撤销更改"
+
+msgid "Undo it from the history when you're back online."
+msgstr "恢复联网后可在历史记录中撤销。"
+
+msgid "Undo needs a connection"
+msgstr "撤销操作需要网络连接"
+
+msgid "Undo this batch"
+msgstr "撤销此批次"
+
+msgid "Undo this batch?"
+msgstr "撤销此批次操作?"
+
+msgid "Undo: {summary}"
+msgstr "撤销:{summary}"
+
+msgid "Undone"
+msgstr "已撤销"
+
+msgid "Unit"
+msgstr "单位"
+
+msgid "Unit price"
+msgstr "单价"
+
+msgid "Unknown device"
+msgstr "未知设备"
+
+msgid "Unlinked {name}"
+msgstr "已解除与 {name} 的关联"
+
+msgid "Unlinked from a purchase"
+msgstr "已取消与购买记录的关联"
+
+msgid "Unnamed"
+msgstr "未命名"
+
+msgid "Unnamed file"
+msgstr "未命名文件"
+
+msgid "Unnamed thing"
+msgstr "未命名物品"
+
+msgid "Unpin {name}"
+msgstr "取消置顶 {name}"
+
+msgid "Unplaced"
+msgstr "未摆放"
+
+msgid "Unplaced for now"
+msgstr "暂不放置"
+
+msgid "Unticked become <0>not here0> when you finish."
+msgstr "完成后,未勾选的物品将被标记为<0>不在此处0>。"
+
+msgid "Until {to}"
+msgstr "直至 {to}"
+
+msgid "Until {until}"
+msgstr "至 {until}"
+
+msgid "Until a date"
+msgstr "截至某日期"
+
+msgid "Until setup is finished, anyone who can open this address could try to claim the server. Finish it now."
+msgstr "在完成初始设置前,任何能打开此地址的人都可能尝试认领该服务器。请立即完成设置。"
+
+msgid "Untitled"
+msgstr "未命名"
+
+msgid "Untitled draft"
+msgstr "未命名草稿"
+
+msgid "Up to"
+msgstr "上限为"
+
+msgid "Up to {0}"
+msgstr "最多 {0}"
+
+msgctxt "map: go up a floor"
+msgid "Up to {0}"
+msgstr "最多 {0}"
+
+msgid "Update Kept to finish syncing."
+msgstr "请更新 Kept 以完成同步。"
+
+msgid "Updated"
+msgstr "已更新"
+
+msgid "Uploading"
+msgstr "正在上传"
+
+msgid "Uploading…"
+msgstr "正在上传…"
+
+msgid "US dollar"
+msgstr "美元"
+
+msgid "Use a backup code instead"
+msgstr "改用备用恢复码"
+
+msgid "Use a different way"
+msgstr "改用其他方式"
+
+msgid "Use a passkey"
+msgstr "使用通行密钥 (Passkey)"
+
+msgid "Use Add here to put the first thing in <0>{name}0>."
+msgstr "点击此处的“添加”,将第一件物品放入 <0>{name}0>。"
+
+msgid "Use Add here to put the first thing in."
+msgstr "点击「在此添加」放入第一件物品。"
+
+msgid "Use another label"
+msgstr "使用其他标签"
+
+msgid "Use Groq's listed price"
+msgstr "使用 Groq 官方标价"
+
+msgid "Use it"
+msgstr "使用它"
+
+msgid "Use my authenticator app instead"
+msgstr "改用我的身份验证器应用"
+
+msgid "Use the system camera"
+msgstr "使用系统相机"
+
+msgid "Used by {0}."
+msgstr "正在被 {0} 使用。"
+
+msgid "Used by imports and the API. Made from the label; English letters, digits and _."
+msgstr "供导入和 API 使用。由标签生成,仅支持英文字母、数字和下划线 _。"
+
+msgid "Used up and restocked, like batteries."
+msgstr "会消耗并定期补货的物品,例如电池。"
+
+msgid "Used up by"
+msgstr "用完日期"
+
+msgid "Used when Kept is in Arabic, for amounts, dates and counts. Short IDs, codes and serials always stay 0–9."
+msgstr "当 Kept 切换为阿拉伯语时,用于金额、日期和数量的数字格式。短 ID、编码和序列号始终保持 0–9。"
+
+msgid "Username"
+msgstr "用户名"
+
+msgid "Users"
+msgstr "用户"
+
+msgid "Uses the AI provider connected for {name}."
+msgstr "使用为 {name} 连接的 AI 服务商。"
+
+msgid "Uses up"
+msgstr "消耗"
+
+msgid "Usual warranty"
+msgstr "常规保修期"
+
+msgid "Usual warranty, in months"
+msgstr "常规保修期(月)"
+
+msgid "Vacation home"
+msgstr "度假屋"
+
+msgid "Vehicles"
+msgstr "车辆"
+
+msgid "vendor"
+msgstr "供应商"
+
+msgid "Vendor"
+msgstr "商家"
+
+msgid "Vendor added"
+msgstr "商家已添加"
+
+msgid "Vendor changed"
+msgstr "商家已更改"
+
+msgid "Vendor deleted"
+msgstr "商家已删除"
+
+msgid "Vendor merged"
+msgstr "商家已合并"
+
+msgid "Vendors"
+msgstr "商家"
+
+msgid "Version"
+msgstr "版本"
+
+msgid "Viewer"
+msgstr "查看者"
+
+msgid "viewer in {n}"
+msgstr "{n} 的访客"
+
+msgid "Viewers"
+msgstr "查看者"
+
+msgid "Viewers can't check boxes. Ask a member or an admin of this location."
+msgstr "查看者无法勾选。请联系此空间的成员或管理员。"
+
+msgid "Viewers look around and copy links. They can't change anything."
+msgstr "查看者可以浏览并复制链接,无法修改任何内容。"
+
+msgid "Views"
+msgstr "视图"
+
+msgid "Waiting · ID pending"
+msgstr "等待中 · ID 待分配"
+
+msgid "Waiting for {provider} · about {seconds} s"
+msgstr "正在等待 {provider} · 约 {seconds} 秒"
+
+msgid "Waiting for {provider} · next in line"
+msgstr "正在等待 {provider} · 排队中"
+
+msgid "Waiting for a place"
+msgstr "等待选择位置"
+
+msgid "Waiting for an AI provider · <0>Connect one in Settings → AI0>"
+msgstr "正在等待 AI 服务商 · <0>请在“设置 → AI”中连接0>"
+
+msgid "Waiting for an AI provider · ask an admin to connect one"
+msgstr "等待配置 AI 服务商 · 请联系管理员连接"
+
+msgid "Waiting for the AI provider"
+msgstr "正在等待 AI 服务商响应"
+
+msgid "Waiting to start…"
+msgstr "正在等待开始…"
+
+msgid "Waiting: {0}"
+msgstr "等待中:{0}"
+
+msgid "Waiting: AI is paused"
+msgstr "等待中:AI 已暂停"
+
+msgid "Warranty"
+msgstr "保修"
+
+msgid "Warranty claim page"
+msgstr "保修理赔页面"
+
+msgid "Warranty claims"
+msgstr "保修理赔"
+
+msgid "Warranty claims page"
+msgstr "保修理赔页面"
+
+msgid "warranty end"
+msgstr "保修结束日期"
+
+msgid "Warranty until 2027"
+msgstr "保修至 2027 年"
+
+msgid "Was in"
+msgstr "原在位置"
+
+msgid "We sent a link to <0>{current}0>. Open it to confirm the change; then a second link goes to <1>{next}1>. Each link works once, for an hour. Until the second one is opened, you sign in with your current address."
+msgstr "我们已向 <0>{current}0> 发送了一封确认链接。打开它确认变更后,第二个链接会发送到 <1>{next}1>。每个链接仅限一小时内使用一次。在打开第二个链接之前,你仍需使用当前邮箱登录。"
+
+msgid "Web link"
+msgstr "网页链接"
+
+msgid "Webhooks, share links and exports you made for {name} stop working."
+msgstr "你为 {name} 创建的 Webhook、共享链接和导出文件都将失效。"
+
+msgid "Website"
+msgstr "网站"
+
+msgid "Welcome, {name}"
+msgstr "欢迎,{name}"
+
+msgid "What {0} is"
+msgstr "{0} 是什么"
+
+msgid "What happened to it"
+msgstr "发生情况"
+
+msgid "What happens to what's inside"
+msgstr "如何处理里面的物品"
+
+msgid "What it changed no longer exists."
+msgstr "它所修改的对象已不存在。"
+
+msgid "What it shows stays."
+msgstr "其显示内容将保持不变。"
+
+msgid "What should {displayName} track?"
+msgstr "{displayName} 要记录哪些内容?"
+
+msgid "What the box should hold"
+msgstr "箱内应放物品"
+
+msgid "What to include"
+msgstr "包含内容"
+
+msgid "What to track"
+msgstr "追踪内容"
+
+msgid "What to track changed"
+msgstr "已更改追踪内容"
+
+msgid "What you trash waits here for 30 days, so a slip of the finger is never final."
+msgstr "移入回收站的内容会在此保留 30 天,误删也能随时挽回。"
+
+msgid "What you would call it out loud."
+msgstr "你平时口头会怎么称呼它。"
+
+msgid "What's inside stays inside. Its link and label keep working."
+msgstr "里面的物品会保留在原处。其链接与标签继续有效。"
+
+msgid "What's this place called?"
+msgstr "这个位置叫什么?"
+
+msgid "When"
+msgstr "时间"
+
+msgid "When AI fills in a thing here, it adds search words in each of these languages, so anyone can find it in their own."
+msgstr "当 AI 在此填写物品信息时,会自动附带这些语言的搜索关键词,方便每位成员用自己的语言搜索。"
+
+msgid "When Kept started for the first time, it printed a one-time setup code in the server's logs. Entering it shows you're the person who installed this server. The code stops working once it's used."
+msgstr "Kept 首次启动时,会在服务器日志中输出一个一次性设置码。输入该设置码即证明你是安装此服务器的人。设置码使用一次后即失效。"
+
+msgid "When two places are really the same one"
+msgstr "当两个位置实际上指同一处时"
+
+msgid "When you save"
+msgstr "保存时生效"
+
+msgid "Where it came from"
+msgstr "来源"
+
+msgid "Where it is"
+msgstr "当前位置"
+
+msgid "Where it was going was trashed in the meantime."
+msgstr "目标位置在此期间已被移入回收站。"
+
+msgid "Where it was is still in the trash, so it's in the Unplaced area now."
+msgstr "它原先所在的位置仍在回收站中,因此目前暂置于「未放置」区域。"
+
+msgid "Where to"
+msgstr "目标位置"
+
+msgid "Where to find it"
+msgstr "存放位置"
+
+msgid "Which {0} to keep"
+msgstr "保留哪个 {0}"
+
+msgid "Which one is it?"
+msgstr "是哪一项?"
+
+msgid "Which one stays"
+msgstr "保留哪一个"
+
+msgid "Which one stays?"
+msgstr "保留哪一个?"
+
+msgid "Which room are you in?"
+msgstr "你在哪个房间?"
+
+msgid "Who can reveal {name}"
+msgstr "谁可以查看 {name}"
+
+msgid "Who can see this location, and what each person can do"
+msgstr "谁可以查看此空间,以及每位成员的操作权限"
+
+msgid "Who sees it"
+msgstr "谁可以查看"
+
+msgid "Whose"
+msgstr "归属人"
+
+msgid "Will be confirmed when you accept"
+msgstr "采纳时将一并确认"
+
+msgid "Will be left out when you accept"
+msgstr "确认采纳时将被忽略"
+
+msgid "Working out what this changes"
+msgstr "正在计算影响范围"
+
+msgid "Works"
+msgstr "正常"
+
+msgid "Works offline. The claim stays pending until it syncs; if another phone claimed this label first, you'll be told."
+msgstr "支持离线操作。标签领用会在同步前保持待处理状态;若另一台手机已先领用,系统会通知你。"
+
+msgid "yes"
+msgstr "是"
+
+msgid "Yes"
+msgstr "是"
+
+msgid "Yes or no"
+msgstr "是 / 否"
+
+msgid "Yesterday"
+msgstr "昨天"
+
+msgid "Yesterday · {long}"
+msgstr "昨天 · {long}"
+
+msgid "You"
+msgstr "你"
+
+msgid "You already have <0>{0}0>."
+msgstr "你已经拥有 <0>{0}0>。"
+
+msgid "You can change these any time in Settings → Admin."
+msgstr "你随时可以在「设置 → 管理」中更改这些设置。"
+
+msgid "You can look, not change"
+msgstr "仅可查看,不可修改"
+
+msgid "You can no longer change things there."
+msgstr "你已无法再在那里修改内容。"
+
+msgid "You can restore it from Trash for 30 days."
+msgstr "30 天内可从回收站恢复。"
+
+msgid "You can still take photos with your phone's camera app, or pick ones you have."
+msgstr "你仍可使用手机自带相机拍照,或从相册选取已有照片。"
+
+msgid "You can view your locations but not change them, so there is nothing here for you to review."
+msgstr "你对所在空间仅有查看权限、无修改权限,因此这里没有需要你审核的内容。"
+
+msgid "You changed <0>{name}0>."
+msgstr "你修改了 <0>{name}0>。"
+
+msgid "You don't have permission to do that."
+msgstr "你没有权限执行此操作。"
+
+msgid "You have 100 saved views, the most there can be. Delete one to save this."
+msgstr "你已保存了 100 个视图(已达上限)。请先删除一个再保存当前视图。"
+
+msgid "You left {name}"
+msgstr "你已退出 {name}"
+
+msgid "You lose access to {name}. What you added stays in {name}."
+msgstr "你将失去对 {name} 的访问权限。你在 {name} 中添加的内容会保留。"
+
+msgid "You lose this admin area straight away. Your own locations and things stay. Another admin can make you one again."
+msgstr "你将立即失去此管理区域的权限。你自己的空间和物品会保留。其他管理员之后可重新为你授权。"
+
+msgid "You opened a link to change the email address you sign in with. Confirm it here."
+msgstr "你打开了用于更改登录邮箱的链接。请在此确认。"
+
+msgid "You opened a sign-in link. Continue to sign in on this device."
+msgstr "你打开了一个登录链接。请继续以在此设备上登录。"
+
+msgid "You own it"
+msgstr "由你拥有"
+
+msgid "You sign in with <0>{current}0>. To change it, we send a link to that address first, then one to the new address."
+msgstr "你当前使用 <0>{current}0> 登录。如需更改,我们会先向当前邮箱发送一封验证链接,然后再向新邮箱发送一封。"
+
+msgid "You were removed from that location."
+msgstr "你已被移出该空间。"
+
+msgid "You, the owner, can always reveal it. Each reveal is recorded in the history."
+msgstr "作为所有者,你随时可以查看该内容。每次查看都会记入历史记录。"
+
+msgid "You're a member"
+msgstr "你是成员"
+
+msgid "You're a viewer"
+msgstr "你是查看者"
+
+msgid "You're a viewer here"
+msgstr "你是此空间的查看者"
+
+msgid "You're already in {name}"
+msgstr "你已经在 {name} 中了"
+
+msgid "You're an admin"
+msgstr "你是管理员"
+
+msgid "You're carrying this one."
+msgstr "你正拿着这件物品。"
+
+msgid "Your access ends {until}"
+msgstr "你的访问权限将于 {until} 到期"
+
+msgid "Your account"
+msgstr "你的账号"
+
+msgid "Your account is ready. Sign in to continue."
+msgstr "你的账号已准备就绪,请登录以继续。"
+
+msgid "Your account's own kind"
+msgstr "你账户的自建类型"
+
+msgid "Your account's own type"
+msgstr "你账号自建的类型"
+
+msgid "your AI provider"
+msgstr "你的 AI 服务商"
+
+msgid "Your current address confirmed the change. We sent a link to the new address: open it to finish. It works once, for an hour. Until then, you sign in with your current address."
+msgstr "当前邮箱已确认此次更改。我们已向新邮箱发送了一封确认邮件:点击其中的链接即可完成更改。链接单次有效,有效期 1 小时。在此之前,你仍需使用当前邮箱登录。"
+
+msgid "Your email address changed"
+msgstr "你的邮箱地址已更改"
+
+msgid "Your name"
+msgstr "你的名字"
+
+msgid "Your new password works now. Every device that was signed in has been signed out."
+msgstr "新密码已生效。所有已登录的设备均已退出登录。"
+
+msgid "Your own"
+msgstr "你自己的"
+
+msgid "Your password"
+msgstr "你的密码"
+
+msgid "Your PDF is ready"
+msgstr "你的 PDF 已就绪"
+
+msgid "Your session ended. Sign in again."
+msgstr "登录会话已过期,请重新登录。"
+
+msgid "Your things of this type use the copy, and you can change it."
+msgstr "你名下该类型的物品将使用此副本,且你可以自由修改。"
+
+msgid "Yours"
+msgstr "你的"
+
+msgid "Z to A"
+msgstr "Z 到 A"
+
+msgid "· attempt {0} of request <0>{1}0>"
+msgstr "· 请求 <0>{1}0> 的第 {0} 次尝试"
+
+msgid "· from the price table"
+msgstr "· 来自价格表"
+
+msgid "· from the price table (version {0})"
+msgstr "· 来自价格表(版本 {0})"
+
+msgid "· from the price table, added later"
+msgstr "· 来自价格表,后续已补充"
+
+msgid "· reported by the provider"
+msgstr "· 由服务商上报"
+
+msgid "\"Test connection\""
+msgstr "“测试连接”"
+
+msgid "({0} of them reasoning)"
+msgstr "(其中 {0} 用于推理)"
+
+msgid "(the default)"
+msgstr "(默认)"
+
+msgid "{0, plural, one {# AI call} other {# AI calls}}"
+msgstr "{0, plural, one {# 次 AI 调用} other {# 次 AI 调用}}"
+
+msgid "{0, plural, one {# call costed} other {# calls costed}}"
+msgstr "{0, plural, one {# 次调用已计费} other {# 次调用已计费}}"
+
+msgid "{0, plural, one {# call had no price, so it isn't in the estimate.} other {# calls had no price, so they aren't in the estimate.}}"
+msgstr "{0, plural, one {# 次调用没有价格信息,因此未计入估算。} other {# 次调用没有价格信息,因此未计入估算。}}"
+
+msgid "{0, plural, one {# call this month has no price and isn't counted. Add prices, or set a token cap too.} other {# calls this month have no price and aren't counted. Add prices, or set a token cap too.}}"
+msgstr "{0, plural, one {本月有 # 次调用未配置单价,因此未计入费用。请补充单价,或同时设置 Token 上限。} other {本月有 # 次调用未配置单价,因此未计入费用。请补充单价,或同时设置 Token 上限。}}"
+
+msgid "{0, plural, one {# call with unknown cost} other {# calls with unknown cost}}"
+msgstr "{0, plural, one {# 次调用费用未知} other {# 次调用费用未知}}"
+
+msgid "{0, plural, one {# image} other {# images}}"
+msgstr "{0, plural, one {# 张图片} other {# 张图片}}"
+
+msgid "{0, plural, one {# photo is being named} other {# photos are being named}}"
+msgstr "{0, plural, one {正在为 # 张照片命名} other {正在为 # 张照片命名}}"
+
+msgid "{0, plural, one {# photo was captured before AI was connected, so it has no name yet.} other {# photos were captured before AI was connected, so they have no names yet.}}"
+msgstr "{0, plural, one {有 # 张照片是在连接 AI 之前拍摄的,因此尚未命名。} other {有 # 张照片是在连接 AI 之前拍摄的,因此尚未命名。}}"
+
+msgid "{0, plural, one {# price proposed from the listing. Nothing is saved until you save it.} other {# prices proposed from the listing. Nothing is saved until you save them.}}"
+msgstr "{0, plural, one {已根据商品页面建议 # 个价格。在你保存前不会写入记录。} other {已根据商品页面建议 # 个价格。在你保存前不会写入记录。}}"
+
+msgid "{0} a day"
+msgstr "每天 {0}"
+
+msgid "{0} a month"
+msgstr "每月 {0}"
+
+msgid "{0} an image"
+msgstr "{0} 图片"
+
+msgid "{0} cached"
+msgstr "已缓存 {0}"
+
+msgid "{0} in · {1} out"
+msgstr "{0} 借入 · {1} 借出"
+
+msgid "{0} of {1} · {2}% so far"
+msgstr "{0} / {1} · 目前已完成 {2}%"
+
+msgid "{0} of {1} tokens · {2}% so far"
+msgstr "{0} / {1} tokens · 目前已用 {2}%"
+
+msgid "{0} sent"
+msgstr "已发送 {0}"
+
+msgid "{0} to {1}"
+msgstr "{0} 至 {1}"
+
+msgid "{0} tokens"
+msgstr "{0} tokens"
+
+msgid "{0} tokens a minute"
+msgstr "每分钟 {0} 个 token"
+
+msgid "{0} tokens so far"
+msgstr "目前已使用 {0} tokens"
+
+msgid "{0} unknown"
+msgstr "{0} 项未知"
+
+msgid "{0}% used"
+msgstr "已使用 {0}%"
+
+msgid "{held, plural, one {# held back by Kept} other {# held back by Kept}}"
+msgstr "{held, plural, one {# 项由 Kept 暂缓} other {# 项由 Kept 暂缓}}"
+
+msgid "{name}'s terms, checked {0}"
+msgstr "{name} 服务条款,核对日期:{0}"
+
+msgid "{provider} isn't answering · retrying at {at}"
+msgstr "{provider} 无响应 · 将于 {at} 重试"
+
+msgid "{provider} rejected the key · Replace key"
+msgstr "{provider} 拒绝了该密钥 · 更换密钥"
+
+msgid "{who} in the account"
+msgstr "账号中的 {who}"
+
+msgid "{who} on this server's key"
+msgstr "{who}(使用本服务器密钥)"
+
+msgid "{who}'s account"
+msgstr "{who} 的账号"
+
+msgid "<0>{0}0> · {person}"
+msgstr "<0>{0}0> · {person}"
+
+msgid "<0>{model}0> is no longer offered by {provName}. Pick another."
+msgstr "{provName} 已不再提供 <0>{model}0>,请改选其他模型。"
+
+msgid "<0>{payer}0>'s account (the server's key would have been next)"
+msgstr "<0>{payer}0> 的账号(否则将使用服务器密钥)"
+
+msgid "<0>{payer}0>'s personal key (their account's key would have been next)"
+msgstr "<0>{payer}0> 的个人密钥(否则将使用其所属账号的密钥)"
+
+msgid "<0>{who}0> has used {0} of {1} this month."
+msgstr "<0>{who}0> 本月已使用 {0} / {1}。"
+
+msgid "<0>{who}0> has used {0} of {1} tokens this month."
+msgstr "<0>{who}0> 本月已使用 {0} / {1} tokens。"
+
+msgid "~{0} tokens each"
+msgstr "每条约 {0} tokens"
+
+msgid "~{0} tokens, image included"
+msgstr "约 {0} 个 token(含图片)"
+
+msgid "1 or more calls (each tool it uses adds one)"
+msgstr "1 次或多次调用(每次使用工具会增加 1 次)"
+
+msgid "a cap or budget was reached"
+msgstr "已达到配额或预算上限"
+
+msgid "a deleted person"
+msgstr "已删除的成员"
+
+msgid "A deleted person"
+msgstr "已删除的成员"
+
+msgid "a few tokens"
+msgstr "少量 tokens"
+
+msgid "A model you chose is no longer offered by {0}"
+msgstr "{0} 已不再提供你选择的模型"
+
+msgid "A nameplate: {0} tokens · {1}"
+msgstr "铭牌识别:{0} tokens · {1}"
+
+msgid "a personal key"
+msgstr "个人密钥"
+
+msgid "A personal key"
+msgstr "个人密钥"
+
+msgid "A receipt: {0} tokens · {1}"
+msgstr "一张收据:{0} 个 token · {1}"
+
+msgid "A server on your own network (an address like 192.168.x.x) needs private addresses allowed on this server."
+msgstr "连接局域网内的服务器(例如 192.168.x.x 地址)需要在本服务器上开启允许内网地址。"
+
+msgid "A server you run yourself keeps what you let it keep."
+msgstr "自建服务器只保存你允许保存的内容。"
+
+msgid "Add a price"
+msgstr "添加价格"
+
+msgid "add a price to see cost"
+msgstr "添加价格以查看费用"
+
+msgid "Add a price to see cost. Until then Kept counts tokens only."
+msgstr "添加价格即可查看费用;在此之前 Kept 仅统计 tokens 数量。"
+
+msgid "Admin settings"
+msgstr "管理员设置"
+
+msgid "Advanced"
+msgstr "高级"
+
+msgid "AI · {provider} · {tokens} tokens"
+msgstr "AI · {provider} · {tokens} tokens"
+
+msgid "AI call"
+msgstr "AI 调用"
+
+msgid "AI calls"
+msgstr "AI 调用次数"
+
+msgid "AI for <0>{who}0> was paused by hand. Resume it, and the photos waiting are named now, oldest first."
+msgstr "<0>{who}0> 的 AI 已被手动暂停。恢复后,等待中的照片将按拍摄先后顺序立即开始识别命名。"
+
+msgid "AI here is then limited only by the other caps that apply."
+msgstr "此处的 AI 用量此后仅受其他适用的上限限制。"
+
+msgid "AI in <0>{locationName}0> is paid by <1>{owner}1>'s account."
+msgstr "<0>{locationName}0> 中的 AI 费用由 <1>{owner}1> 的账号承担。"
+
+msgid "AI in <0>{locationName}0> is paid by its owner's account."
+msgstr "<0>{locationName}0> 的 AI 费用由其拥有者的账号承担。"
+
+msgid "AI in <0>{locationName}0> uses a personal key."
+msgstr "<0>{locationName}0> 中的 AI 使用个人密钥。"
+
+msgid "AI in <0>{locationName}0> uses this server's key."
+msgstr "<0>{locationName}0> 中的 AI 使用此服务器的密钥。"
+
+msgid "AI is off in <0>{locationName}0>: no AI provider is connected."
+msgstr "<0>{locationName}0> 中的 AI 已关闭:未连接任何 AI 服务商。"
+
+msgid "AI isn't working here"
+msgstr "AI 在此处不可用"
+
+msgid "AI isn't working here · ask {who}"
+msgstr "AI 在此处不可用 · 请联系 {who}"
+
+msgid "AI resumed"
+msgstr "AI 已恢复"
+
+msgid "AI usage in {name}"
+msgstr "{name} 的 AI 用量"
+
+msgid "AI was paused by hand"
+msgstr "AI 已被手动暂停"
+
+msgid "AI wasn't sure of these. Confirm or reject each one: nothing is saved until you accept."
+msgstr "AI 对以下内容不太确定。请逐项确认或拒绝:在你采纳前不会保存任何内容。"
+
+msgid "AI will read the photo again"
+msgstr "AI 将重新识别此照片"
+
+msgid "An account's key"
+msgstr "某账号的密钥"
+
+msgid "An odometer: {0} tokens · {1}"
+msgstr "里程表:{0} tokens · {1}"
+
+msgid "and {0} of {1} tokens"
+msgstr "以及 {0} / {1} tokens"
+
+msgid "Answered in {0}"
+msgstr "回复于 {0}"
+
+msgid "Ask an instance admin."
+msgstr "请联系实例管理员。"
+
+msgid "assistant"
+msgstr "AI 助手"
+
+msgid "Assistant follow-up"
+msgstr "AI 助手追问"
+
+msgid "Assistant question"
+msgstr "AI 助手提问"
+
+msgid "At your last 30 days' pace: {0} a month ({1, plural, one {# call} other {# calls}})"
+msgstr "按最近 30 天用量估算:每月 {0}({1, plural, one {# 次调用} other {# 次调用}})"
+
+msgid "At your last 30 days' pace: ~{0} tokens a month ({1, plural, one {# call} other {# calls}})"
+msgstr "按最近 30 天用量估算:每月约 {0} tokens({1, plural, one {# 次调用} other {# 次调用}})"
+
+msgid "attempt {0}"
+msgstr "第 {0} 次尝试"
+
+msgid "Attempt {0} · {1} · {2}"
+msgstr "第 {0} 次尝试 · {1} · {2}"
+
+msgid "Base URL"
+msgstr "基础 URL"
+
+msgid "Budget · {0}"
+msgstr "预算 · {0}"
+
+msgid "Budgets per task"
+msgstr "按任务分配预算"
+
+msgid "by day"
+msgstr "按天"
+
+msgid "cached {0}"
+msgstr "已缓存 {0}"
+
+msgid "Cached input, per million (optional)"
+msgstr "缓存输入单价,每百万 tokens(可选)"
+
+msgid "Calls"
+msgstr "调用次数"
+
+msgid "Calls from now have cost unknown until a new price is saved. Past calls keep theirs."
+msgstr "在保存新价格之前,后续调用的费用将显示为未知。历史调用保留原费用。"
+
+msgid "Calls so far"
+msgstr "累计调用次数"
+
+msgid "Can't be above the account's cap"
+msgstr "不能超过账号总上限"
+
+msgid "Captures still save; naming waits."
+msgstr "采集内容仍会保存,稍后再命名。"
+
+msgid "Change the limit"
+msgstr "更改上限"
+
+msgid "Cost"
+msgstr "费用"
+
+msgid "cost hidden"
+msgstr "费用已隐藏"
+
+msgid "Cost this month's unpriced calls"
+msgstr "计算本月未计价调用的费用"
+
+msgid "Cost unknown: no price for this model when it ran."
+msgstr "费用未知:运行时该模型尚无定价。"
+
+msgid "Costed {0} calls with this price"
+msgstr "已按此价格统计 {0} 次调用"
+
+msgid "Couldn't read this photo · {0}"
+msgstr "无法读取此照片 · {0}"
+
+msgid "Custom"
+msgstr "自定义"
+
+msgid "Custom model id ({label})"
+msgstr "自定义模型 ID({label})"
+
+msgid "Cut off"
+msgstr "停止记录"
+
+msgid "Day"
+msgstr "日"
+
+msgid "Download the recovery kit first"
+msgstr "请先下载恢复工具包"
+
+msgid "Each account on this server's key"
+msgstr "每个使用此服务器密钥的账号"
+
+msgid "Each assistant question"
+msgstr "每次助手提问"
+
+msgid "Each captured photo"
+msgstr "每张拍摄的照片"
+
+msgid "Each captured photo will appear here with what it cost."
+msgstr "每张录入的照片及其识别费用都会显示在这里。"
+
+msgid "Each label or nameplate photo"
+msgstr "每张标签或铭牌照片"
+
+msgid "Each meter reading"
+msgstr "每条表计读数"
+
+msgid "Each receipt (up to 4 pages in one call)"
+msgstr "每张收据(单次调用最多 4 页)"
+
+msgid "Empty: the input rate."
+msgstr "留空则使用输入时的汇率。"
+
+msgid "Empty: the output rate."
+msgstr "留空则使用输出单价。"
+
+msgid "Enter an amount above zero."
+msgstr "请输入大于零的金额。"
+
+msgid "Every call"
+msgstr "每次调用"
+
+msgid "Export CSV"
+msgstr "导出 CSV"
+
+msgid "Fill from {0}'s listing"
+msgstr "从 {0} 的清单填入"
+
+msgid "Find a model"
+msgstr "查找模型"
+
+msgid "Find a thing"
+msgstr "查找物品"
+
+msgid "finish reason <0>{0}0>"
+msgstr "结束原因 <0>{0}0>"
+
+msgid "For {0}, as chosen under Advanced."
+msgstr "应用于 {0}(按高级设置中的选择)。"
+
+msgid "For example, 100 photos and 20 receipts a month ≈ 120 calls."
+msgstr "例如:每月 100 张照片和 20 张收据 ≈ 120 次调用。"
+
+msgid "From the listing"
+msgstr "来自公开报价"
+
+msgid "From the provider's listing of {0}. Check it, then save."
+msgstr "来自服务商 {0} 的公开报价。核对后即可保存。"
+
+msgid "from this server"
+msgstr "来自此服务器"
+
+msgid "from you"
+msgstr "来自你"
+
+msgid "from your account"
+msgstr "来自你的账号"
+
+msgid "From your last 30 days, for actions you've used at least 5 times."
+msgstr "统计过去 30 天内你使用过至少 5 次的操作。"
+
+msgid "from your own use once you've tried it"
+msgstr "试用后结合你自己的实际使用情况填写"
+
+msgid "Get a Groq key"
+msgstr "获取 Groq 密钥"
+
+msgid "Has an image"
+msgstr "包含图片"
+
+msgid "Hidden in this location"
+msgstr "在此空间中已隐藏"
+
+msgid "High"
+msgstr "高"
+
+msgid "How {name} keeps and uses what it receives is set by its own terms for API customers."
+msgstr "{name} 如何留存和使用其接收到的数据,由其 API 客户服务条款决定。"
+
+msgid "How it went"
+msgstr "情况说明"
+
+msgid "Images"
+msgstr "图片"
+
+msgid "In Kept's test on {date}, it read receipts, labels and nameplates correctly for the least money of any model measured:"
+msgstr "在 Kept 于 {date} 进行的测试中,该模型以最低的成本准确识别了收据、标签和铭牌:"
+
+msgid "Input {0} · output {1} per million tokens"
+msgstr "每百万 token:输入 {0} · 输出 {1}"
+
+msgid "Input, per million tokens"
+msgstr "输入,每百万 tokens"
+
+msgid "Inside the account's {0}"
+msgstr "位于账户的 {0} 中"
+
+msgid "Invalid answer"
+msgstr "无效响应"
+
+msgid "Keep paused"
+msgstr "保持暂停"
+
+msgid "Kept (background)"
+msgstr "Kept(后台)"
+
+msgid "Kept can't tell which provider this key is for. Choose it under Advanced."
+msgstr "Kept 无法自动识别此密钥所属的服务商,请在「高级」中手动选择。"
+
+msgid "Kept estimated {0} before sending."
+msgstr "Kept 在发送前估算为 {0}。"
+
+msgid "Kept fills in {0}'s address."
+msgstr "Kept 会自动填入 {0} 的地址。"
+
+msgid "Kept reads the provider from the key. It sends the key to the server once and never shows it again."
+msgstr "Kept 会根据密钥自动识别服务商。密钥仅向服务器发送一次,之后不会再显示。"
+
+msgid "Key saved"
+msgstr "密钥已保存"
+
+msgid "Key saved · <0>••••{0}0> · never shown again"
+msgstr "密钥已保存 · <0>••••{0}0> · 以后不再显示"
+
+msgid "Keyword only (no embeddings model)"
+msgstr "仅关键词(无向量模型)"
+
+msgid "Label or nameplate"
+msgstr "标签或铭牌"
+
+msgid "Last 3 months"
+msgstr "最近 3 个月"
+
+msgid "Last month"
+msgstr "上个月"
+
+msgid "Limit a person"
+msgstr "限制成员"
+
+msgid "Limit removed"
+msgstr "已移除限制"
+
+msgid "Limit saved"
+msgstr "上限已保存"
+
+msgid "Limits"
+msgstr "限额"
+
+msgid "Listed {0}"
+msgstr "已列出 {0}"
+
+msgid "Looks like a {0} key."
+msgstr "看起来像 {0} 密钥。"
+
+msgid "Low (the default)"
+msgstr "低(默认)"
+
+msgid "Measured by Kept on {0} with Groq · <0>{1}0>"
+msgstr "由 Kept 于 {0} 通过 Groq 实测 · <0>{1}0>"
+
+msgid "Medium"
+msgstr "中"
+
+msgid "Meter reading"
+msgstr "表计读数"
+
+msgid "Minimal"
+msgstr "极简"
+
+msgid "Model or request id"
+msgstr "模型或请求 ID"
+
+msgid "Models"
+msgstr "型号"
+
+msgid "Models saved"
+msgstr "模型设置已保存"
+
+msgid "Money a month"
+msgstr "每月费用"
+
+msgid "Monthly caps"
+msgstr "每月上限"
+
+msgid "Monthly limit set"
+msgstr "已设置每月上限"
+
+msgid "More reasoning can read harder photos, and costs more output tokens."
+msgstr "开启更强的推理深度可以识别更复杂的照片,但会消耗更多输出 tokens。"
+
+msgid "My AI usage"
+msgstr "我的 AI 用量"
+
+msgid "New price version"
+msgstr "新价格版本"
+
+msgid "New version"
+msgstr "新版本"
+
+msgid "No AI calls yet"
+msgstr "暂无 AI 调用记录"
+
+msgid "No budget: the monthly caps above apply."
+msgstr "无额外预算限制:适用上方的每月上限。"
+
+msgid "No closer key was set, so it fell back to this one."
+msgstr "未设置更近层级的密钥,因此已回退使用此密钥。"
+
+msgid "no cost"
+msgstr "无费用"
+
+msgid "No limit"
+msgstr "无限制"
+
+msgid "No location"
+msgstr "无所属空间"
+
+msgid "No location · {person}"
+msgstr "无所属空间 · {person}"
+
+msgid "No monthly limit. Set one under Advanced."
+msgstr "无每月上限。可在「高级」中设置。"
+
+msgid "No price from now"
+msgstr "此后无单价"
+
+msgid "No prices yet: an instance admin adds them. Until then, cost is unknown."
+msgstr "暂无价格配置:需要实例管理员添加。在此之前,费用将显示为未知。"
+
+msgid "No prices yet. Without one, calls are counted in tokens and their cost is unknown."
+msgstr "尚未设置单价。未设置时,调用仅统计 Token 数量,费用显示为未知。"
+
+msgid "None known"
+msgstr "未知"
+
+msgid "Not sent"
+msgstr "未发送"
+
+msgid "Not sent: Kept held it back, so nothing was used."
+msgstr "未发送:Kept 已拦截该请求,未产生任何用量。"
+
+msgid "Not set: name things by hand"
+msgstr "未设置:手动命名物品"
+
+msgid "Nothing is capped unless you choose. At 80% you get a warning; at the limit AI pauses until the 1st, and captures still save."
+msgstr "除非你主动设置,否则不设上限。达到 80% 时会发出提醒;达到上限后 AI 将暂停至次月 1 日,采集内容仍会正常保存。"
+
+msgid "Nothing is paused that you can resume."
+msgstr "目前没有可恢复的已暂停任务。"
+
+msgid "Nothing is sent to the provider until you resume. Captures still save, and their naming waits."
+msgstr "在恢复前不会向服务商发送任何内容。采集的照片仍会保存,待恢复后再进行识别命名。"
+
+msgid "Nothing: it wasn't sent."
+msgstr "无消耗:请求未发送。"
+
+msgid "OK"
+msgstr "确定"
+
+msgid "Only a copy of the photo with location and camera data removed, never the original. The fixed instructions and your location's languages. For the assistant, your question and the inventory it looks up, within your role. Never secret fields."
+msgstr "仅发送移除位置和相机数据的照片副本,绝不发送原图。同时包含固定提示词和你的空间语言。使用 AI 助手时,还会包含你的提问及其在你的权限范围内检索到的库存,但绝不包含私密字段。"
+
+msgid "Only a copy with the location and camera data removed. Kept never keeps it."
+msgstr "仅发送移除了位置和相机信息的副本,Kept 不会保留该副本。"
+
+msgid "Only where the provider bills images apart from tokens."
+msgstr "仅在服务商将图像费用与 token 分开计费时适用。"
+
+msgid "Open the status page"
+msgstr "打开状态页"
+
+msgid "Open the thing"
+msgstr "打开物品"
+
+msgid "Open the thing it read"
+msgstr "打开识别到的物品"
+
+msgid "OpenAI-compatible"
+msgstr "OpenAI 兼容接口"
+
+msgid "OpenAI-compatible (Ollama, LM Studio, …)"
+msgstr "OpenAI 兼容接口(Ollama、LM Studio 等)"
+
+msgid "Optional. A token cap also counts calls whose cost is unknown."
+msgstr "可选。Token 上限也会计入费用未知的调用。"
+
+msgid "Other attempts of this request"
+msgstr "此请求的其他重试记录"
+
+msgid "Other providers work as well: OpenAI, Anthropic, Google, OpenRouter, or your own OpenAI-compatible server. Paste their key, or choose one under Advanced."
+msgstr "其他服务商同样适用:OpenAI、Anthropic、Google、OpenRouter,或你自己的 OpenAI 兼容服务器。直接粘贴密钥,或在「高级」中选择对应服务商。"
+
+msgid "Outcome"
+msgstr "结果"
+
+msgid "Outcomes"
+msgstr "处理结果"
+
+msgid "Output, per million tokens"
+msgstr "输出,每百万 tokens"
+
+msgid "Over budget"
+msgstr "超出预算"
+
+msgid "Paid by"
+msgstr "付款人"
+
+msgid "Paste the new key"
+msgstr "粘贴新密钥"
+
+msgid "Paste your key"
+msgstr "粘贴你的密钥"
+
+msgid "Pause AI"
+msgstr "暂停 AI"
+
+msgid "Pause AI?"
+msgstr "暂停 AI?"
+
+msgid "Paused"
+msgstr "已暂停"
+
+msgid "Per image (optional)"
+msgstr "每张图片(可选)"
+
+msgid "Period"
+msgstr "周期"
+
+msgid "photos and receipts"
+msgstr "照片与收据"
+
+msgid "Photos and receipts"
+msgstr "照片与收据"
+
+msgid "Photos: not read"
+msgstr "照片:未读取"
+
+msgid "Pick another"
+msgstr "重新选择"
+
+msgid "Price saved as version {0}"
+msgstr "价格已保存为版本 {0}"
+
+msgid "Prices"
+msgstr "价格"
+
+msgid "Provider"
+msgstr "服务商"
+
+msgid "Provider error"
+msgstr "服务商错误"
+
+msgid "Raise and resume"
+msgstr "提高上限并恢复"
+
+msgid "Raise the cap to ({0})"
+msgstr "将上限提高至({0})"
+
+msgid "Raise the limit to (tokens)"
+msgstr "将上限提高至(tokens)"
+
+msgid "Rate-limited"
+msgstr "请求受限"
+
+msgid "Re-run extraction"
+msgstr "重新提取"
+
+msgid "reasoning {0}"
+msgstr "推理 {0}"
+
+msgid "Reasoning effort"
+msgstr "推理强度"
+
+msgid "Reasoning, per million (optional)"
+msgstr "推理输出单价,每百万 token(可选)"
+
+msgid "Recommended"
+msgstr "推荐"
+
+msgid "Recommended: Groq"
+msgstr "推荐:Groq"
+
+msgid "Refresh list"
+msgstr "刷新列表"
+
+msgid "Refreshing…"
+msgstr "正在刷新…"
+
+msgid "Refused"
+msgstr "已拒赔"
+
+msgid "Remove the cap"
+msgstr "取消上限"
+
+msgid "Remove this limit?"
+msgstr "移除此限额?"
+
+msgid "Replace key"
+msgstr "更换密钥"
+
+msgid "Replaced"
+msgstr "已更换"
+
+msgid "Resume"
+msgstr "继续"
+
+msgid "Resume AI"
+msgstr "恢复 AI"
+
+msgid "Resume now"
+msgstr "立即恢复"
+
+msgid "Run Test to check photos"
+msgstr "运行“测试”以检查照片识别"
+
+msgid "Save a key first: Kept then loads the provider's models to choose from."
+msgstr "请先保存密钥:Kept 随后会加载该服务商的可用模型供你选择。"
+
+msgid "Save and test"
+msgstr "保存并测试"
+
+msgid "Save limit"
+msgstr "保存限额"
+
+msgid "Save models"
+msgstr "保存模型"
+
+msgid "Save price"
+msgstr "保存价格"
+
+msgid "Saving adds a new version from now. Calls already costed keep their price."
+msgstr "保存后将从现在起启用新价格版本。已计费的调用保留原价格。"
+
+msgid "search"
+msgstr "搜索"
+
+msgid "Search AI calls"
+msgstr "搜索 AI 调用"
+
+msgid "Search index"
+msgstr "搜索索引"
+
+msgid "Semantic search"
+msgstr "语义搜索"
+
+msgid "Set {0} a month"
+msgstr "已设为每月 {0}"
+
+msgid "Set {0} tokens a month"
+msgstr "设为每月 {0} tokens"
+
+msgid "Set a limit"
+msgstr "设置限额"
+
+msgid "Set a limit for {0}"
+msgstr "为 {0} 设置上限"
+
+msgid "Set a monthly limit?"
+msgstr "要设置每月限额吗?"
+
+msgid "Set a price in Admin → AI"
+msgstr "请在“管理 → AI”中设置价格"
+
+msgid "Show as a table"
+msgstr "以表格显示"
+
+msgid "Show earlier versions"
+msgstr "显示更早版本"
+
+msgid "Since {0}"
+msgstr "自 {0}"
+
+msgid "so far"
+msgstr "迄今"
+
+msgid "Stop pricing"
+msgstr "停止计价"
+
+msgid "Stop pricing {0}?"
+msgstr "停止为 {0} 计价?"
+
+msgid "Structured answers"
+msgstr "结构化回答"
+
+msgid "Structured answers: not given"
+msgstr "结构化回答:未提供"
+
+msgid "Task"
+msgstr "任务"
+
+msgid "Test"
+msgstr "测试"
+
+msgid "Test connection"
+msgstr "测试连接"
+
+msgid "Test needs a connection"
+msgstr "测试需要网络连接"
+
+msgid "Test used {0} tokens with <0>{1}0>"
+msgstr "测试使用 <0>{1}0> 消耗了 {0} 个 token"
+
+msgid "Tests"
+msgstr "测试"
+
+msgid "That currency isn't turned on. An instance admin can add it."
+msgstr "该币种尚未启用,可由实例管理员添加。"
+
+msgid "That was a test with made-up photos; Kept's evaluation with real photos checks it again. Groq has no embeddings model, so semantic search needs another provider or stays keyword only. On the key tier Kept measured, Groq reads {low}–{high} photos a minute; Kept paces to it, so a {photos}-photo session is named over {fromMin}–{toMin} minutes while you carry on."
+msgstr "此前为模拟照片测试;Kept 使用真实照片评估时会再次校验。Groq 不提供向量模型,因此语义搜索需使用其他服务商,否则仅支持关键词搜索。按 Kept 实测的密钥速率档位,Groq 每分钟可识别 {low}–{high} 张照片;Kept 会自动控制请求节奏,因此一次 {photos} 张照片的会话将在你继续使用期间于 {fromMin}–{toMin} 分钟内完成命名。"
+
+msgid "That was already undone"
+msgstr "该操作此前已撤销"
+
+msgid "The account"
+msgstr "该账号"
+
+msgid "the account's key"
+msgstr "该账号的密钥"
+
+msgid "The account's lower cap applies first."
+msgstr "以账号中较低的上限为准。"
+
+msgid "the answer was cut off"
+msgstr "回答被截断"
+
+msgid "the answer wasn't in the shape Kept asked for"
+msgstr "返回结果不符合 Kept 要求的格式"
+
+msgid "The cheapest reliable result in Kept's test: about USD {perReceipt} a receipt, with <0>{0}0>. On the key tier Kept measured, Groq reads {low}–{high} photos a minute; Kept paces to it."
+msgstr "Kept 实测中性价比最高的可靠方案:使用 <0>{0}0> 时,每张收据约 {perReceipt} 美元。在 Kept 实测的密钥等级下,Groq 每分钟可读取 {low}–{high} 张照片;Kept 会自动匹配该速率。"
+
+msgid "The first AI key is a secret Kept must be able to recover. Save the recovery kit on the status page, then paste the key again."
+msgstr "配置首个 AI 密钥前,Kept 必须能够恢复加密数据。请先在状态页保存恢复工具包,再重新粘贴密钥。"
+
+msgid "The listing has no prices Kept can use."
+msgstr "该列表没有 Kept 可用的价格信息。"
+
+msgid "the monthly cap was reached"
+msgstr "已达到本月额度上限"
+
+msgid "the monthly token limit was reached"
+msgstr "已达到本月 Token 上限"
+
+msgid "The person who runs this server needs to save the recovery kit before the first AI key. Ask them, then paste the key again."
+msgstr "在添加第一个 AI 密钥前,服务器管理员需要先保存恢复工具包。请联系管理员保存后,再重新粘贴密钥。"
+
+msgid "the provider asked Kept to slow down"
+msgstr "服务商要求 Kept 降低请求速率"
+
+msgid "the provider couldn't be reached"
+msgstr "无法连接到服务商"
+
+msgid "the provider declined it"
+msgstr "服务商拒绝了该请求"
+
+msgid "the provider had an error"
+msgstr "服务商返回错误"
+
+msgid "the provider refused the request"
+msgstr "服务商拒绝了该请求"
+
+msgid "the provider rejected the key"
+msgstr "服务商拒绝了该密钥"
+
+msgid "the provider timed out"
+msgstr "服务商响应超时"
+
+msgid "the provider's content filter declined it"
+msgstr "服务商的内容安全过滤拒绝了此请求"
+
+msgid "the provider's quota is used up"
+msgstr "服务商额度已用尽"
+
+msgid "the provider's rate limit was reached"
+msgstr "已达到服务商速率限制"
+
+msgid "The test didn't run"
+msgstr "测试未运行"
+
+msgid "The whole account"
+msgstr "整个账号"
+
+msgid "This key pays for the homes your account owns."
+msgstr "此密钥用于支付你账户名下各空间产生的费用。"
+
+msgid "This model can't read photos here. Pick another under Advanced."
+msgstr "此模型不支持在这里识别照片,请在「高级」中更换其他模型。"
+
+msgid "This month"
+msgstr "本月"
+
+msgid "This provider has no embeddings model: search stays keyword only."
+msgstr "该服务商没有向量嵌入模型:搜索仅支持关键词匹配。"
+
+msgid "This provider lists no chat model."
+msgstr "此服务商未列出对话模型。"
+
+msgid "This provider lists no model that reads photos."
+msgstr "此服务商未列出支持识图的模型。"
+
+msgid "This server, overall"
+msgstr "此服务器整体概况"
+
+msgid "this server's key"
+msgstr "此服务器的密钥"
+
+msgid "This server's key"
+msgstr "此服务器的密钥"
+
+msgid "This server's key pays for every location and person with no closer key. Limit what each account may spend below."
+msgstr "此服务器密钥会为所有未单独设置密钥的空间和用户付费。请在下方限制各账号的消费上限。"
+
+msgid "Time"
+msgstr "时间"
+
+msgid "Timed out"
+msgstr "已超时"
+
+msgid "To"
+msgstr "至"
+
+msgid "today's AI budget was used up"
+msgstr "今日 AI 预算已用完"
+
+msgid "Tokens"
+msgstr "令牌"
+
+msgid "Tokens a day"
+msgstr "每日 tokens 上限"
+
+msgid "Tokens a minute"
+msgstr "每分钟 tokens 上限"
+
+msgid "Tokens a month"
+msgstr "每月 Token 用量"
+
+msgid "Tokens are counted; the cost shows once an instance admin sets a price."
+msgstr "系统会统计 tokens 用量;待实例管理员配置价格后将显示具体费用。"
+
+msgid "Tokens are counted; the cost shows once the model has a price."
+msgstr "已统计 Token 用量;为该模型设置单价后即可显示费用。"
+
+msgid "Tokens by day"
+msgstr "每日 token 用量"
+
+msgid "Tokens by day, stacked by task"
+msgstr "按天统计的 Token 用量(按任务堆叠)"
+
+msgid "tokens vary"
+msgstr "tokens 视情况而定"
+
+msgid "Using"
+msgstr "当前使用"
+
+msgid "Version {0}"
+msgstr "版本 {0}"
+
+msgid "Waiting for {provider} · about {secs} s"
+msgstr "正在等待 {provider} · 约 {secs} 秒"
+
+msgid "What for"
+msgstr "用途"
+
+msgid "What is sent to {name}"
+msgstr "发送给 {name} 的内容"
+
+msgid "What is sent to the provider"
+msgstr "发送给服务商的内容"
+
+msgid "What it belongs to opens, with what's inside. A worn label, or no camera? Type the code instead."
+msgstr "扫码即可打开对应物品或位置及其内部内容。标签磨损或没有摄像头?可直接输入编号。"
+
+msgid "What uses AI in Kept"
+msgstr "Kept 中哪些功能使用 AI"
+
+msgid "Where and who"
+msgstr "位置与人员"
+
+msgid "Where your key lives"
+msgstr "密钥存放位置"
+
+msgid "Who pays for AI"
+msgstr "AI 费用承担方"
+
+msgid "Whose usage"
+msgstr "用量统计对象"
+
+msgid "Why: {0}"
+msgstr "原因:{0}"
+
+msgid "Why?"
+msgstr "为什么?"
+
+msgid "Your key"
+msgstr "你的密钥"
+
+msgid "Your limit in <0>{0}0>'s account"
+msgstr "你在 <0>{0}0> 账号下的额度上限"
+
+msgid "Your personal key"
+msgstr "你的个人密钥"
+
+msgid "{0, plural, one {own code} other {own codes}}"
+msgstr "{0, plural, one {个自定义编号} other {个自定义编号}}"
+
+msgid "{0, plural, one {place to make} other {places to make}}"
+msgstr "{0, plural, one {个待创建位置} other {个待创建位置}}"
+
+msgid "{0, plural, one {purchase to record} other {purchases to record}}"
+msgstr "{0, plural, one {笔待记录购买} other {笔待记录购买}}"
+
+msgid "{0, plural, one {row skipped} other {rows skipped}}"
+msgstr "{0, plural, one {行已跳过} other {行已跳过}}"
+
+msgid "{0, plural, one {row with cells kept as text} other {rows with cells kept as text}}"
+msgstr "{0, plural, one {行(单元格保留为纯文本)} other {行(单元格保留为纯文本)}}"
+
+msgid "{0, plural, one {thing to add} other {things to add}}"
+msgstr "{0, plural, one {件待添加物品} other {件待添加物品}}"
+
+msgid "{column} goes to"
+msgstr "{column} 对应字段"
+
+msgid "{done} of {of} rows"
+msgstr "{done} / {of} 行"
+
+msgid "{fieldName} is already {earlier}. One column each."
+msgstr "{fieldName} 已被设为「{earlier}」。每个字段只能对应一列。"
+
+msgid "{rows, plural, one {# row. Say what each column is; the guesses come from the headers.} other {# rows. Say what each column is; the guesses come from the headers.}}"
+msgstr "{rows, plural, one {共 # 行。请指定每一列的含义;当前猜测依据表头生成。} other {共 # 行。请指定每一列的含义;当前猜测依据表头生成。}}"
+
+msgid "{things, plural, one {Import # thing} other {Import # things}}"
+msgstr "{things, plural, one {导入 # 件物品} other {导入 # 件物品}}"
+
+msgid "{total, plural, one {# row} other {# rows}}"
+msgstr "{total, plural, one {# 行} other {# 行}}"
+
+msgid "<0>{0}0> into <1>{name}1>"
+msgstr "<0>{0}0> 放入 <1>{name}1>"
+
+msgid "A few choices"
+msgstr "多个选项"
+
+msgid "A place name is longer than {max} characters; kept in the notes."
+msgstr "有位置名称超过 {max} 个字符,已保存至备注。"
+
+msgid "A purchase needs a date; kept in the notes."
+msgstr "购买记录需要日期;已保留在备注中。"
+
+msgid "A purchase needs a price; kept in the notes."
+msgstr "购买记录需要价格;已保留在备注中。"
+
+msgid "A quote in row {quoteRow} is never closed, so the rows after it may be read wrongly. Check the file if the values look odd."
+msgstr "第 {quoteRow} 行的引号未闭合,后续行可能解析有误。如果数值异常,请检查该文件。"
+
+msgid "A spreadsheet (CSV)"
+msgstr "电子表格 (CSV)"
+
+msgid "A type's field: {key}"
+msgstr "类型字段:{key}"
+
+msgid "A type's field…"
+msgstr "类型字段…"
+
+msgid "Adjust mapping"
+msgstr "调整字段映射"
+
+msgid "All {rows} rows are done. Rows that were skipped in the check were left out; cells kept as text are in each thing's notes."
+msgstr "全部 {rows} 行已处理完成。预检中跳过的行已略过;保留为纯文本的单元格内容已写入对应物品的备注。"
+
+msgid "Already imported by an earlier import, so it's skipped."
+msgstr "已在更早的导入中导入过,已跳过。"
+
+msgid "Also where a row goes when its place isn't made."
+msgstr "当某一行对应的位置尚未创建时,物品也会放入此处。"
+
+msgid "An import takes at most {limit} rows. Split the file and import each part."
+msgstr "单次导入最多支持 {limit} 行。请拆分文件后分批导入。"
+
+msgid "As the type's field is written in Settings → Account → Types, like warranty_months."
+msgstr "与“设置 → 账户 → 类型”中字段的写法一致,例如 warranty_months。"
+
+msgid "Cancel the import"
+msgstr "取消导入"
+
+msgid "Cancel the import?"
+msgstr "取消导入?"
+
+msgid "Cancelled"
+msgstr "已取消"
+
+msgid "Check the import"
+msgstr "检查导入"
+
+msgid "Check the import first, then import."
+msgstr "请先预检导入文件,然后再执行导入。"
+
+msgid "Checked"
+msgstr "已核对"
+
+msgid "Choose a CSV file"
+msgstr "选择 CSV 文件"
+
+msgid "Choose a CSV file, or drop one here. It's read on this device first; nothing is imported until you've checked it."
+msgstr "选择一个 CSV 文件,或将其拖放到此处。文件会先在此设备上解析,在你核对确认前不会导入。"
+
+msgid "Choose the file"
+msgstr "选择文件"
+
+msgid "Choose the location first."
+msgstr "请先选择空间。"
+
+msgid "Choose which column is the name: every thing needs one."
+msgstr "选择哪一列作为名称:每件物品都必须有名称。"
+
+msgid "Column"
+msgstr "列"
+
+msgid "Column {n}"
+msgstr "第 {n} 列"
+
+msgid "Columns"
+msgstr "列"
+
+msgid "Dates are written as"
+msgstr "日期格式"
+
+msgid "Don't import"
+msgstr "不导入"
+
+msgid "Empty in every row"
+msgstr "在每一行中均为空"
+
+msgid "Field key"
+msgstr "字段键名"
+
+msgid "For rows whose currency column is empty."
+msgstr "用于币种列为空的行。"
+
+msgid "Import another file"
+msgstr "导入另一个文件"
+
+msgid "Import cancelled"
+msgstr "导入已取消"
+
+msgid "Import from"
+msgstr "导入来源"
+
+msgid "Import into"
+msgstr "导入至"
+
+msgid "Imported"
+msgstr "已导入"
+
+msgid "Imported into {locationName}"
+msgstr "已导入到 {locationName}"
+
+msgid "Imported rows"
+msgstr "已导入行"
+
+msgid "Importing"
+msgstr "正在导入"
+
+msgid "Importing adds things to a location, so it's for its owners and admins. Ask one of them, or import into a location of your own."
+msgstr "导入会向空间中添加物品,因此仅限所有者和管理员操作。请联系他们,或导入到你自己的空间中。"
+
+msgid "Importing into {locationName}"
+msgstr "正在导入到 {locationName}"
+
+msgid "Importing…"
+msgstr "正在导入…"
+
+msgid "In any of Kept's languages. Off, the type is kept in the notes."
+msgstr "支持 Kept 的任意界面语言。关闭后,类型信息将保留在备注中。"
+
+msgid "It hasn't moved for a while. What it already imported stays."
+msgstr "进度已停滞一段时间。已导入的内容会保留。"
+
+msgid "It stopped after {rows} rows. What it imported before stopping stays in {locationName}."
+msgstr "在第 {rows} 行后停止。停止前已导入的数据仍保留在 {locationName} 中。"
+
+msgid "It stops after the rows it's working on. Things it already imported stay; import the file again later and those rows are skipped."
+msgstr "将在处理完当前行后停止。已导入的物品会保留;稍后重新导入该文件时会自动跳过已导入的行。"
+
+msgid "Keep importing"
+msgstr "继续导入"
+
+msgid "Longer than {max} characters; kept in the notes."
+msgstr "超过 {max} 个字符;已保存至备注。"
+
+msgid "Longer than a brand name can be ({max} characters); kept in the notes."
+msgstr "超出了品牌名称的最大长度({max} 个字符);已保留在备注中。"
+
+msgid "Longer than a shop name can be ({max} characters); kept in the notes."
+msgstr "超出商店名称长度上限({max} 个字符);已保存至备注。"
+
+msgid "Lowercase letters, digits and _, starting with a letter."
+msgstr "仅限小写字母、数字和 _,且需以字母开头。"
+
+msgid "Make the places the file names that don't exist yet"
+msgstr "自动创建文件中提到但尚不存在的位置"
+
+msgid "Manual link"
+msgstr "说明书链接"
+
+msgid "Mapped"
+msgstr "已映射"
+
+msgid "Match the columns"
+msgstr "匹配列字段"
+
+msgid "Match the type column to your types by name"
+msgstr "按名称将“类型”列匹配到你的现有类型"
+
+msgid "Money is turned off in this location; kept in the notes."
+msgstr "此空间已关闭金额功能,已保存在备注中。"
+
+msgid "No column is a currency, so every price is in this one."
+msgstr "没有币种列,因此所有价格均使用此币种。"
+
+msgid "No column is a place, so every row goes here."
+msgstr "没有位置列,因此所有行都将导入此处。"
+
+msgid "No name, so it's skipped."
+msgstr "没有名称,已跳过。"
+
+msgid "No such place, and new places aren't made; it goes to the default place."
+msgstr "无此位置,且未启用自动创建新位置;已放入默认位置。"
+
+msgid "No type has this name; kept in the notes."
+msgstr "没有同名类型;已保存在备注中。"
+
+msgid "Not a condition Kept knows; kept in the notes."
+msgstr "Kept 不识别此成色状态;已保存在备注中。"
+
+msgid "Not a currency turned on in Kept; the price is kept in the notes."
+msgstr "Kept 中未启用该币种;价格已保存在备注中。"
+
+msgid "Not a date written as {format}; kept in the notes."
+msgstr "不是符合 {format} 格式的日期;已保留在备注中。"
+
+msgid "Not a field of this row's type; kept in the notes."
+msgstr "不是此行所属类型的字段;已保留在备注中。"
+
+msgid "Not a price; kept in the notes."
+msgstr "非有效价格;已保存在备注中。"
+
+msgid "Not a quantity; kept in the notes."
+msgstr "非有效数量;已保留在备注中。"
+
+msgid "Not a value this field can hold; kept in the notes."
+msgstr "此字段无法容纳该值;已保留在备注中。"
+
+msgid "Not a web link (http or https); kept in the notes."
+msgstr "不是网页链接(http 或 https);已保存在备注中。"
+
+msgid "Not added as a tag (too long, or too many tags); kept in the notes."
+msgstr "未添加为分类标签(过长或标签过多);已保留在备注中。"
+
+msgid "Not added as another name (too long, or too many); kept in the notes."
+msgstr "未添加为别名(过长或数量过多);已保留在备注中。"
+
+msgid "Not checked"
+msgstr "未检查"
+
+msgid "Nothing to import"
+msgstr "没有可导入的内容"
+
+msgid "Only a consumable can have quantity 0; kept in the notes."
+msgstr "只有耗材的数量可以为 0;已保留在备注中。"
+
+msgid "Only owners and admins can import"
+msgstr "仅所有者与管理员可执行导入"
+
+msgid "Only owners and admins can import into a location."
+msgstr "只有拥有者和管理员才能向空间导入数据。"
+
+msgid "Only owners and admins of this location can import into it."
+msgstr "只有此空间的拥有者和管理员才能向其中导入数据。"
+
+msgid "Open {locationName}"
+msgstr "打开 {locationName}"
+
+msgid "Partly as text"
+msgstr "部分以纯文本保存"
+
+msgid "Place (a path like Garage > Shelf A)"
+msgstr "位置(如“车库 > A 架”这样的路径)"
+
+msgid "Prices are in"
+msgstr "价格币种"
+
+msgid "Purchase date"
+msgstr "购买日期"
+
+msgid "Recent imports here"
+msgstr "此处的近期导入"
+
+msgid "Resume to carry on from row {done}"
+msgstr "继续从第 {done} 行恢复处理"
+
+msgid "Row {row}, {column}, is longer than {limitCell} characters. Shorten it and try again."
+msgstr "第 {row} 行“{column}”超过 {limitCell} 个字符。请缩短后重试。"
+
+msgid "Row {rowNo}"
+msgstr "第 {rowNo} 行"
+
+msgid "Row ID (so a re-import skips it)"
+msgstr "行 ID(便于重新导入时跳过重复项)"
+
+msgid "Row number, column or reason"
+msgstr "行号、列名或原因"
+
+msgid "Rows"
+msgstr "行数"
+
+msgid "Rows without a place go to"
+msgstr "未指定位置的行将放入"
+
+msgid "Search {locationName}"
+msgstr "搜索 {locationName}"
+
+msgid "Search rows"
+msgstr "搜索行"
+
+msgid "Secret fields aren't imported; add it on the thing."
+msgstr "加密字段不会导入;请在对应物品页面中手动添加。"
+
+msgid "Skipped"
+msgstr "已跳过"
+
+msgid "Start again"
+msgstr "重新开始"
+
+msgid "Stopped"
+msgstr "已停止"
+
+msgid "The check reads every row the way the import will, and changes nothing. It shows what would be added, what would be kept as text, and what would be skipped."
+msgstr "预检会按正式导入的方式逐行读取,但不会修改任何数据。它会显示哪些内容将被添加、哪些将保留为纯文本,以及哪些将被跳过。"
+
+msgid "The checklist is back on Home"
+msgstr "引导清单已重新显示在首页"
+
+msgid "The date is in the future; kept in the notes."
+msgstr "日期在未来;已保存在备注中。"
+
+msgid "The dates in the file read more than one way (is 03/04 the 3rd of April or the 4th of March?). Check this one."
+msgstr "文件中的日期存在多种解读方式(例如 03/04 是 4 月 3 日还是 3 月 4 日?)。请核对此日期。"
+
+msgid "The file has no rows."
+msgstr "该文件没有任何数据行。"
+
+msgid "The import stopped"
+msgstr "导入已停止"
+
+msgid "The location's currency ({locationCurrency})"
+msgstr "空间货币({locationCurrency})"
+
+msgid "The name is longer than {max} characters, so it's skipped."
+msgstr "名称超过了 {max} 个字符,已跳过。"
+
+msgid "The notes are cut to {max} characters."
+msgstr "备注已截断为 {max} 个字符。"
+
+msgid "The place column separates places with"
+msgstr "位置列分隔多个位置的符号"
+
+msgid "The purchase is incomplete; kept in the notes."
+msgstr "采购信息不完整,已保存在备注中。"
+
+msgid "The row has no type, so it has no fields; kept in the notes."
+msgstr "该行没有类型,因此没有对应字段;已保留在备注中。"
+
+msgid "The same as row {row}, so it's skipped."
+msgstr "与第 {row} 行相同,已跳过。"
+
+msgid "This code is already on something else, so it isn't added."
+msgstr "此编码已绑定在其他物品上,因此未予添加。"
+
+msgid "This file can't be imported"
+msgstr "无法导入此文件"
+
+msgid "This file can't be read as CSV. Save it from your spreadsheet as CSV (UTF-8) and try again."
+msgstr "无法将该文件读取为 CSV。请在电子表格软件中将其另存为 CSV (UTF-8) 后重试。"
+
+msgid "This file has {columns} columns; an import takes at most {limitColumns}."
+msgstr "此文件包含 {columns} 列;单次导入最多支持 {limitColumns} 列。"
+
+msgid "This file has {rows} rows; an import takes at most {limitRows}. Split it into smaller files."
+msgstr "此文件共有 {rows} 行;单次导入最多支持 {limitRows} 行。请拆分为较小的文件。"
+
+msgid "This file has no rows under its header row."
+msgstr "此文件表头行下方没有任何数据行。"
+
+msgid "This file is {mb} MB; an import takes at most {limitMb} MB. Split it into smaller files."
+msgstr "此文件大小为 {mb} MB;单次导入上限为 {limitMb} MB。请拆分为更小的文件。"
+
+msgid "This type is counted one by one; kept in the notes."
+msgstr "此类型按件单独计数;原数量保存在备注中。"
+
+msgid "Types aren't matched by name; kept in the notes."
+msgstr "类型未按名称匹配;已保留在备注中。"
+
+msgid "Values in {column}"
+msgstr "{column} 中的值"
+
+msgid "What the import will do"
+msgstr "导入将执行以下操作"
+
+msgid "Worked out from the dates in the file."
+msgstr "根据文件中的日期推算得出。"
+
+msgid "You can leave this page; the import carries on, and Settings → Import shows how far it got."
+msgstr "你可以离开此页面,导入会在后台继续进行,可在“设置 → 导入”中查看进度。"
+
+msgid "{0, plural, one {Shared with 1 location} other {Shared with # locations}}"
+msgstr "{0, plural, one {已共享给 1 个空间} other {已共享给 # 个空间}}"
+
+msgid "Also the new thing's name, until you type one."
+msgstr "在你输入名称前,这也会作为新物品的名称。"
+
+msgid "Couldn't delete it"
+msgstr "无法删除"
+
+msgid "Couldn't save it"
+msgstr "无法保存"
+
+msgid "Edit template"
+msgstr "编辑模板"
+
+msgid "From a template"
+msgstr "从模板创建"
+
+msgid "From the template <0>{0}0>"
+msgstr "来自模板 <0>{0}0>"
+
+msgid "Members of these locations can start new things from it."
+msgstr "这些空间的成员都可以基于它创建新物品。"
+
+msgid "New template"
+msgstr "新建模板"
+
+msgid "New things can start from this one's details. Prices and secret fields stay behind."
+msgstr "新建物品时可以此物品的详情作为模板。价格与敏感字段不会被带入。"
+
+msgid "No templates are shared with this location yet. Owners and admins make them in Settings → Account → Templates."
+msgstr "尚无模板共享到此空间。所有者和管理员可在“设置 → 账户 → 模板”中创建。"
+
+msgid "No templates yet"
+msgstr "暂无模板"
+
+msgid "Prices and secret fields are never part of a template."
+msgstr "价格和加密字段绝不会包含在模板中。"
+
+msgid "Save as template"
+msgstr "存为模板"
+
+msgid "Save the details you type again and again, and share them with your locations. Start one here, or use Save as template on a thing."
+msgstr "把经常重复填写的详情保存下来,并在你的各个空间之间共享。你可以在这里新建模板,或在任意物品页面点击「存为模板」。"
+
+msgid "Saved {n} as a template"
+msgstr "已将 {n} 保存为模板"
+
+msgid "Search templates"
+msgstr "搜索模板"
+
+msgid "Share it with at least one location."
+msgstr "请至少共享给一个空间。"
+
+msgid "Share with"
+msgstr "共享给"
+
+msgid "Start from a template"
+msgstr "从模板开始"
+
+msgid "Template name"
+msgstr "模板名称"
+
+msgid "The type's fields"
+msgstr "该类型的字段"
+
+msgid "Things already started from it keep their details."
+msgstr "已从此模板创建的物品会保留其现有详情。"
+
+msgid "Kept labels"
+msgstr "Kept 标签"
+
+msgid "Saved the label images"
+msgstr "已保存标签图片"
+
+msgid "{count, plural, one {# blank label} other {# blank labels}}"
+msgstr "{count, plural, one {# 张空白标签} other {# 张空白标签}}"
+
+msgid "{count, plural, one {# label} other {# labels}}"
+msgstr "{count, plural, one {# 个标签} other {# 个标签}}"
+
+msgid "Back to labels"
+msgstr "返回标签"
+
+msgid "Share as images"
+msgstr "以图片形式分享"
+
+msgid "Share into Kept"
+msgstr "分享到 Kept"
+
+msgid "Print"
+msgstr "打印"
+
+msgid "Printed on {printedOn}. Reprinting prints the same codes."
+msgstr "打印于 {printedOn}。重新打印会生成相同的编码。"
+
+msgid "In the print dialog choose your label printer and this label size."
+msgstr "在打印对话框中选择你的标签打印机和此标签尺寸。"
+
+msgid "Print labels"
+msgstr "打印标签"
+
+msgid "Printing labels is for members and admins of this location."
+msgstr "只有该空间的成员和管理员才能打印标签。"
+
+msgid "Labels are switched off here. Turn them on in What to track."
+msgstr "此处已关闭标签功能。请在“追踪内容”中开启。"
+
+msgid "Labels are switched off here. Ask an admin to turn them on."
+msgstr "此处已关闭标签功能。请联系管理员开启。"
+
+msgid "No location to print labels for"
+msgstr "没有可打印标签的空间"
+
+msgid "Labels are off, or you can only view, in every location you're in."
+msgstr "你所在的所有空间都未开启标签功能,或你仅有查看权限。"
+
+msgid "Labels off"
+msgstr "标签功能已关闭"
+
+msgid "Label everything unprinted"
+msgstr "为所有未打印的项目生成标签"
+
+msgid "Counting…"
+msgstr "正在清点…"
+
+msgid "Every thing here has a printed label"
+msgstr "此处的每件物品都已打印标签"
+
+msgid "{unprinted, plural, one {# thing has no printed label} other {# things have no printed label}}"
+msgstr "{unprinted, plural, one {# 件物品尚未打印标签} other {# 件物品尚未打印标签}}"
+
+msgid "Blank sheet ({s})"
+msgstr "空白标签纸({s})"
+
+msgid "Stick them on now, name them on the first scan. {b} unclaimed here."
+msgstr "现在就可以贴上标签,首次扫码时再命名。此处有 {b} 张未认领标签。"
+
+msgid "Loading recent batches"
+msgstr "正在加载最近批次"
+
+msgid "{n, plural, one {# blank label} other {# blank labels}}"
+msgstr "{n, plural, one {# 张空白标签} other {# 张空白标签}}"
+
+msgid "{n, plural, one {# label} other {# labels}}"
+msgstr "{n, plural, one {# 个标签} other {# 个标签}}"
+
+msgid "Recent batches"
+msgstr "最近批次"
+
+msgid "Printed"
+msgstr "已打印"
+
+msgid "Not confirmed"
+msgstr "未确认"
+
+msgid "Label everything here"
+msgstr "为这里的所有物品生成标签"
+
+msgid "Print labels for what's in here that never had one printed"
+msgstr "为此处尚未打印过标签的所有对象打印标签"
+
+msgid "Print its label"
+msgstr "打印它的标签"
+
+msgid "For the shelf or door; a reprint has the same code"
+msgstr "用于货架或柜门;重新打印的编码保持不变"
+
+msgid "This code stays with {0} for good, so a reprinted label still finds it."
+msgstr "此编码会永久绑定 {0},因此重新打印标签后扫码仍可找到它。"
+
+msgid "{pending, plural, one {# thing was left out: its ID is still pending.} other {# things were left out: their IDs are still pending.}}"
+msgstr "{pending, plural, one {已略过 # 件物品:其编号尚待分配。} other {已略过 # 件物品:其编号尚待分配。}}"
+
+msgid "Printing {countText}"
+msgstr "正在打印 {countText}"
+
+msgid "Nothing to print"
+msgstr "暂无可打印内容"
+
+msgid "Everything here already has a printed label."
+msgstr "此处所有内容都已打印过标签。"
+
+msgid "None of these has an ID yet."
+msgstr "这些项目均尚未分配 ID。"
+
+msgid "They get their IDs when the phone that captured them syncs. Print them then, from \"Print pending labels\" on that phone."
+msgstr "当录入这些物品的手机同步后,它们就会获得正式 ID。届时可在该手机的「打印待分配标签」中进行打印。"
+
+msgid "{count, plural, one {Print # label} other {Print # labels}}"
+msgstr "{count, plural, one {打印 # 枚标签} other {打印 # 枚标签}}"
+
+msgid "Opens the print dialog at {stockTitle}, scale 100%. Afterwards Kept asks \"Printed OK?\" and records the print date."
+msgstr "将以 {stockTitle}、100% 缩放比例打开打印对话框。打印完成后,Kept 会询问“打印是否正常?”并记录打印日期。"
+
+msgid "Opens the print dialog: choose your label printer and this label size. Afterwards Kept asks \"Printed OK?\" and records the print date."
+msgstr "打开打印对话框:选择标签打印机和此标签尺寸。打印后 Kept 会询问「打印正常吗?」并记录打印日期。"
+
+msgid "Label preview"
+msgstr "标签预览"
+
+msgid "Each blank label gets its own code when you print."
+msgstr "每张空白标签在打印时都会分配专属编码。"
+
+msgid "Blank labels"
+msgstr "空白标签"
+
+msgid "Fewer"
+msgstr "更少"
+
+msgid "Stick them on boxes now and name them later: the first scan asks what each one is. This location has {left} unclaimed of at most {cap}."
+msgstr "先将标签贴在箱子上,稍后再命名:首次扫码时会询问每个箱子的内容。当前空间还有 {left} 个未认领标签(上限 {cap} 个)。"
+
+msgid "Print pending labels ({n})"
+msgstr "打印待处理标签({n})"
+
+msgid "Things captured on this phone got their IDs when it synced. Print their labels now."
+msgstr "在此手机上采集的物品已在同步后获得编号。现在可以打印它们的标签。"
+
+msgid "Print these"
+msgstr "打印这些标签"
+
+msgid "Marked as printed"
+msgstr "已标记为已打印"
+
+msgid "Now stick one on and scan it"
+msgstr "现在贴上标签并扫描"
+
+msgid "Tap Scan on Home and point the camera at a label: what it belongs to opens, with what's inside. A label keeps its code for good, so a lost one reprints the same."
+msgstr "在首页轻点“扫码”,将摄像头对准标签,即可打开对应的物品或位置及其中内容。每个标签的编码永久不变,标签丢失后重新打印即可。"
+
+msgid "Printed OK?"
+msgstr "打印效果正常吗?"
+
+msgid "Check that the labels sit inside their cells and that one scans. Yes records today as their print date."
+msgstr "请检查标签是否位于格线内,且能正常扫码。选「是」会将今天记录为打印日期。"
+
+msgid "No, print again"
+msgstr "不,重新打印"
+
+msgid "Yes, printed OK"
+msgstr "是的,打印正常"
+
+msgid "Sheet {n} of {total}"
+msgstr "第 {n} 页,共 {total} 页"
+
+msgid "Start at label"
+msgstr "起始标签格"
+
+msgid "Sheet preview"
+msgstr "打印页预览"
+
+msgid "{usedN} already used"
+msgstr "已用 {usedN}"
+
+msgid "Start at label {start} (row {r}, column {c}). Tap any cell to start there."
+msgstr "从第 {start} 个标签开始(第 {r} 行,第 {c} 列)。轻点任意单元格即可从该格开始。"
+
+msgid "Label {at}, row {rn}, column {cn2}"
+msgstr "标签 {at},第 {rn} 行,第 {cn2} 列"
+
+msgid "These labels take {n} sheets; the next ones start at label 1."
+msgstr "这些标签共占 {n} 页;后续标签将从第 1 张开始。"
+
+msgid "{a} × {b} mm"
+msgstr "{a} × {b} mm"
+
+msgid "{cell} roll"
+msgstr "{cell} 标签卷"
+
+msgid "Label printer · one label per thing"
+msgstr "标签打印机 · 每件物品一张标签"
+
+msgid "{width} mm tape"
+msgstr "{width} mm 标签带"
+
+msgid "Label maker · QR code, short ID and name"
+msgstr "标签打印机 · 二维码、短编号与名称"
+
+msgid "Label maker · short ID large, and the name"
+msgstr "标签打印机 · 大号短 ID 与名称"
+
+msgid "{paper} sheet · {count}"
+msgstr "{paper} 规格 · {count}"
+
+msgid "{cols} × {rows}, each {cell} · QR and code only"
+msgstr "{cols} × {rows},每格 {cell} · 仅二维码与编码"
+
+msgid "{cols} × {rows}, each {cell} · any office printer"
+msgstr "{cols} × {rows},单枚尺寸 {cell} · 通用办公打印机"
+
+msgid "Label stock"
+msgstr "标签纸规格"
+
+msgid "At most 80 characters."
+msgstr "最多 80 个字符。"
+
+msgid "merged from <0>{name}0>"
+msgstr "已从 <0>{name}0> 合并"
+
+msgid "merged from a thing with no name"
+msgstr "合并自一件未命名物品"
+
+msgid "{other, plural, one {# can't be labelled here: it is in the trash or in another location.} other {# can't be labelled here: they are in the trash or in another location.}}"
+msgstr "{other, plural, one {# 项无法在此贴标:它位于回收站或其他空间中。} other {# 项无法在此贴标:它们位于回收站或其他空间中。}}"
+
+msgid "{pending, plural, one {# is waiting to sync: its ID is still pending.} other {# are waiting to sync: their IDs are still pending.}}"
+msgstr "{pending, plural, one {# 项正在等待同步:其 ID 尚待生成。} other {# 项正在等待同步:其 ID 尚待生成。}}"
+
+msgid "Everything listed has been printed since."
+msgstr "所列项目此后均已打印。"
+
+msgid "Nothing here can be labelled now"
+msgstr "此处暂无可制作标签的内容"
+
+msgid "expiry date"
+msgstr "到期日期"
+
+msgid "manufacture date"
+msgstr "生产日期"
+
+msgid "number plate"
+msgstr "车牌号"
+
+msgid "Set this on the thing's page. Here it can only be left out."
+msgstr "请在物品详情页设置此项;此处只能跳过。"
+
+msgid "VIN"
+msgstr "VIN"
+
+msgid "An account on this server's key"
+msgstr "此服务器上的某账号密钥"
+
+msgid "Couldn't get the model list from {provName}: it rejected the key or didn't answer. Check the key, or try again in a minute."
+msgstr "无法从 {provName} 获取模型列表:密钥被拒绝或服务未响应。请检查密钥,或稍后再试。"
+
+msgid "No model list"
+msgstr "无可用模型列表"
+
+msgid "paid by this server"
+msgstr "由当前服务器承担费用"
+
+msgid "paid by you"
+msgstr "由你支付"
+
+msgid "Photos: not sent"
+msgstr "照片:未发送"
+
+msgid "The photo request wasn't sent: AI may be paused, or the provider refused the key."
+msgstr "照片请求未发送:AI 可能已暂停,或服务商拒绝了密钥。"
+
+msgid "This server"
+msgstr "此服务器"
+
+msgid "{max, plural, one {At most # name. Remove one to add another.} other {At most # names. Remove one to add another.}}"
+msgstr "{max, plural, one {最多支持 # 个名称。请先移除一个再添加。} other {最多支持 # 个名称。请先移除一个再添加。}}"
+
+msgid "Barcode lookup"
+msgstr "条形码查询"
+
+msgid "Contact for the lookups"
+msgstr "查询服务联系邮箱"
+
+msgid "Enter a host name only, like kept.home.example: no https:// and no port."
+msgstr "仅输入主机名(如 kept.home.example),不要包含 https:// 或端口号。"
+
+msgid "Enter an email address, or leave it empty."
+msgstr "请输入邮箱地址,或留空。"
+
+msgid "Former addresses"
+msgstr "历史域名"
+
+msgid "Look up products Kept doesn't know by their barcode"
+msgstr "通过条码查询 Kept 暂未收录的商品"
+
+msgid "None. Kept answers only at its own address."
+msgstr "无。Kept 仅在自身地址响应请求。"
+
+msgid "Off. A scanned product barcode finds only what Kept already holds."
+msgstr "关闭。扫描商品条形码时,仅查找 Kept 中已有的物品。"
+
+msgid "Old host name"
+msgstr "旧主机名"
+
+msgid "On. A scanned product barcode Kept doesn't know is looked up in Open Food Facts, Open Products Facts and Open Beauty Facts. Only the barcode is sent."
+msgstr "已开启。扫描到 Kept 未知的商品条形码时,会通过 Open Food Facts、Open Products Facts 和 Open Beauty Facts 查询。仅发送条形码本身。"
+
+msgid "Only the name, like kept.home.example."
+msgstr "仅填写域名,例如 kept.home.example。"
+
+msgid "Remove {host}"
+msgstr "移除 {host}"
+
+msgid "Save contact"
+msgstr "保存联系人"
+
+msgid "That is this server's own address."
+msgstr "这是此服务器自身的地址。"
+
+msgid "That name is already listed."
+msgstr "该名称已在列表中。"
+
+msgid "The databases ask each app for a contact. Kept sends this email with each lookup, and nothing else about you."
+msgstr "数据库会要求每个应用提供联系邮箱。Kept 在每次查询时仅发送此邮箱,不会发送你的其他任何信息。"
+
+msgid "When Kept moves to a new address, list the old names here and point them at this server. A label printed under an old address still opens: the request is sent to this one."
+msgstr "当 Kept 迁移到新地址时,请在此列出旧域名并指向当前服务器。旧地址下打印的标签仍可正常打开:请求会转发到此服务器。"
+
+msgid "{n, plural, one {Picked up # thing} other {Picked up # things}}"
+msgstr "{n, plural, one {已拾取 # 件物品} other {已拾取 # 件物品}}"
+
+msgid "Choose things"
+msgstr "选择物品"
+
+msgid "Couldn't pick them up on this phone."
+msgstr "无法在此手机上读取它们。"
+
+msgid "<0>{name}0> · <1>{meter}1>"
+msgstr "<0>{name}0> · <1>{meter}1>"
+
+msgid "<0>{name}0> · <1>{meterLabel}1> (<2>{unit}2>)"
+msgstr "<0>{name}0> · <1>{meterLabel}1>(<2>{unit}2>)"
+
+msgid "A reading goes on the thing whose meter it is, with the photo as proof. Only things with a meter are listed."
+msgstr "读数会记录在所属表计的物品上,并将照片作为凭证。此处仅列出带有表计的物品。"
+
+msgid "A reading needs a meter: a car's odometer, a generator's hours. Add one on the thing's page, under Meters, then read it here. Until then, take the photo in Thing mode."
+msgstr "记录读数需要先配置表计,例如汽车里程表、发电机运行小时数。请先在物品页面的「表计」下添加表计,再回到此处读取。在此之前,请使用「物品」模式拍照。"
+
+msgid "Choose what was read"
+msgstr "选择已识别的内容"
+
+msgid "Couldn't check which things have a meter"
+msgstr "无法检查哪些物品带有表计"
+
+msgid "Finding things with a meter…"
+msgstr "正在查找带表计的物品…"
+
+msgid "Nothing here has a meter yet"
+msgstr "此处还没有任何带有表计的物品"
+
+msgid "Only things with a meter · tap to change"
+msgstr "仅显示带表计的物品 · 点击切换"
+
+msgid "Reading {meter} of {name}. Change"
+msgstr "正在记录 {name} 的 {meter} 读数。点击更改"
+
+msgid "What was read?"
+msgstr "识别到了什么?"
+
+msgid "Private addresses"
+msgstr "私有网络地址"
+
+msgid "Allow private addresses"
+msgstr "允许内网地址"
+
+msgid "On. An OpenAI-compatible AI provider can be on this server's own network, like a model you run at home."
+msgstr "已开启。OpenAI 兼容的 AI 服务商可以位于当前服务器的同一内网中,例如你在本地运行的大模型。"
+
+msgid "Off. An AI provider's address must be on the public internet."
+msgstr "已关闭。AI 服务商地址必须位于公网。"
+
+msgid "Only for a server you host yourself. While this is on, anyone who can add an AI provider, and any location's admin through a webhook, can make this server send requests to machines on its network, such as your router or other services. A webhook's test shows the status they answer with. The Homebox import and OIDC sign-in can reach that network too."
+msgstr "仅适用于你自己托管的服务器。开启后,任何可添加 AI 服务商的用户以及任意空间管理员(通过 Webhook)都可使本服务器向内网主机(如你的路由器或其他服务)发送请求,Webhook 测试会返回其响应状态码。Homebox 导入与 OIDC 登录同样可访问该内网。"
+
+msgid "That address is on a private network. On a self-hosted server, an instance admin can allow private addresses in Admin → Settings."
+msgstr "该地址位于私有网络中。在自托管服务器上,实例管理员可在“管理 → 设置”中允许访问私有地址。"
+
+msgid "A change couldn't apply: <0>{name}0> was trashed by <1>{by}1>."
+msgstr "有更改未能应用:<0>{name}0> 已被 <1>{by}1> 移入回收站。"
+
+msgid "A change couldn't apply: <0>{name}0> was moved by <1>{by}1>."
+msgstr "有一项变更无法应用:<0>{name}0> 已被 <1>{by}1> 移走。"
+
+msgid "A change couldn't apply: <0>{name}0> was removed by <1>{by}1>."
+msgstr "一项更改未能应用:<0>{name}0> 已被 <1>{by}1> 移除。"
+
+msgid "{unexplained, plural, one {# change needs a look} other {# changes need a look}}"
+msgstr "{unexplained, plural, one {# 项变更需要查看} other {# 项变更需要查看}}"
+
+msgid "{0} For example: <0/>"
+msgstr "{0} 例如:<0/>"
+
+msgid "A code that doesn't match is refused when it's added or imported. Changing the rule never changes the codes you have."
+msgstr "添加或导入编码时,不符合规则的编码会被拒绝。修改规则不会影响现有编码。"
+
+msgid "A regular expression the whole code must match. Capital and small letters count as the same."
+msgstr "整个编码必须匹配的正则表达式。大小写字母视为相同。"
+
+msgid "Add a code"
+msgstr "添加编码"
+
+msgid "An old label's code (from another app)"
+msgstr "旧标签的编码(来自其他应用)"
+
+msgid "Change {code}"
+msgstr "修改 {code}"
+
+msgid "Change {value}"
+msgstr "修改 {value}"
+
+msgid "Changed {code} to {to}"
+msgstr "已将 {code} 更改为 {to}"
+
+msgid "Changed the codes of {name}"
+msgstr "更改了 {name} 的编号"
+
+msgid "Check codes against a format rule"
+msgstr "按格式规则校验编码"
+
+msgid "Check the code: 1 to 100 characters."
+msgstr "请检查编号:长度需为 1 到 100 个字符。"
+
+msgid "Code"
+msgstr "编码"
+
+msgid "Codes that don't match the rule"
+msgstr "不符合规则的编号"
+
+msgid "Codes that don't match the rule ({count})"
+msgstr "不符合规则的编码({count})"
+
+msgid "Digits"
+msgstr "位数"
+
+msgid "Doesn't match this location's format rule ({rule}); kept in the notes."
+msgstr "不符合此空间的格式规则({rule});已保留在备注中。"
+
+msgid "Each new thing here gets the next code, which is never given out again, even after it's removed. Its short ID stays as it is."
+msgstr "这里的每件新物品都会分配下一个编码,即使删除也不会重复分配;其短 ID 保持不变。"
+
+msgid "Every code here matches the rule"
+msgstr "这里的每个编码都符合规则"
+
+msgid "Example"
+msgstr "示例"
+
+msgid "For example: <0/>"
+msgstr "例如:<0/>"
+
+msgid "From an import"
+msgstr "来自导入"
+
+msgid "From Homebox"
+msgstr "来自 Homebox"
+
+msgid "In plain words, for whoever types the code."
+msgstr "用通俗易懂的语言说明规则,方便输入编码的人理解。"
+
+msgid "Kept can't read this pattern. Check its brackets."
+msgstr "Kept 无法解析此格式模式,请检查其中的括号。"
+
+msgid "Message when a code doesn't match"
+msgstr "编码不匹配时的提示消息"
+
+msgid "Next number: <0/>"
+msgstr "下一个编号:<0/>"
+
+msgid "None yet. Add a code you already use, like the number on an asset sticker, to find this by it too."
+msgstr "暂无编码。添加你正在使用的现有编号(如资产贴纸上的编号),之后也可按该编号搜索。"
+
+msgid "Number new things automatically"
+msgstr "自动为新物品编号"
+
+msgid "Open what has it"
+msgstr "打开关联项目"
+
+msgid "Pattern"
+msgstr "模式"
+
+msgid "Prefix"
+msgstr "前缀"
+
+msgid "Remove {value}"
+msgstr "移除 {value}"
+
+msgid "Removed {value}"
+msgstr "已移除 {value}"
+
+msgid "The example doesn't match the pattern."
+msgstr "示例不符合该正则表达式。"
+
+msgid "The format rule took too long to check this code."
+msgstr "格式规则校验此编码耗时过长。"
+
+msgid "The next numbered code, {0}, doesn't match the format rule. Change the prefix or the rule."
+msgstr "下一个编号 {0} 不符合格式规则。请修改前缀或调整规则。"
+
+msgid "The next thing gets <0/>."
+msgstr "下一件物品将获得 <0/>。"
+
+msgid "This code is already on something else here."
+msgstr "此编号已被此处的其他物品或位置占用。"
+
+msgid "This location doesn't number its codes."
+msgstr "此空间未对编号进行自动递增。"
+
+msgid "This pattern takes too long to check on a long code. Make it simpler, for example without a repeat inside a repeat."
+msgstr "此正则表达式在匹配长编码时耗时过长。请简化规则,例如避免在重复分组内嵌套重复。"
+
+msgid "Your codes"
+msgstr "你的恢复码"
+
+msgid "Your own code (checked against your format rule)"
+msgstr "自定义编号(按你的格式规则校验)"
+
+msgid "Your own codes"
+msgstr "你自己的编码"
+
+msgid "Documents"
+msgstr "文档"
+
+msgid "Documents need a connection"
+msgstr "查看文档需要网络连接"
+
+msgid "Their text isn't kept on this phone. They're searched again when you're back online."
+msgstr "其文本内容未缓存在此手机上。重新联网后即可再次搜索。"
+
+msgid "{where} already has the code {code}, on {holder}. Change or remove it on one of them, then move again."
+msgstr "{where} 中已存在编码 {code}(位于 {holder})。请先修改或移除其中一项的编码,然后再移动。"
+
+msgid "{where} already has the code {code}. Change or remove it on one of them, then move again."
+msgstr "{where} 中已有编码 {code}。请先更改或移除其中一项的编码,然后再移动。"
+
+msgid "{unread, plural, one {# unread notification} other {# unread notifications}}"
+msgstr "{unread, plural, one {# 条未读通知} other {# 条未读通知}}"
+
+msgid "A report of your things with their prices, values and receipts, and a pack of the originals to send with a claim."
+msgstr "包含物品价格、估值和收据的清单报告,以及随理赔一并提交的原始凭证资料包。"
+
+msgid "Claim pack"
+msgstr "理赔材料包"
+
+msgid "Exchange rates"
+msgstr "汇率"
+
+msgid "Expiring"
+msgstr "即将过期"
+
+msgid "How Kept reaches you"
+msgstr "Kept 联系你的方式"
+
+msgid "Incident"
+msgstr "事故记录"
+
+msgid "Incidents"
+msgstr "事件记录"
+
+msgid "Insurance report"
+msgstr "保险报告"
+
+msgid "Reminders and alerts"
+msgstr "提醒与告警"
+
+msgid "Reminders that are due, loans that are overdue, and news about your locations, with the next step one tap away."
+msgstr "到期提醒、逾期未还记录以及空间动态,轻点一下即可处理下一步。"
+
+msgid "Report"
+msgstr "报告"
+
+msgid "What your insurer asks for"
+msgstr "保险公司所需的资料"
+
+msgid "Open PDF"
+msgstr "打开 PDF"
+
+msgid "Share"
+msgstr "分享"
+
+msgid "Couldn't share the PDF. Try again."
+msgstr "无法分享 PDF。请重试。"
+
+msgid "Couldn't share the label images. Try again."
+msgstr "无法分享标签图片,请重试。"
+
+msgid "Couldn't share the CSV. Try again."
+msgstr "无法分享 CSV 文件,请重试。"
+
+msgid "Your CSV is ready"
+msgstr "你的 CSV 已就绪"
+
+msgid "Share it to save it to Files or send it on."
+msgstr "可通过分享将其保存到「文件」或发送给他人。"
+
+msgid "This browser can't save files here. Open Kept in Safari to export it."
+msgstr "当前浏览器无法在此保存文件。请在 Safari 中打开 Kept 进行导出。"
+
+msgid "This file can't be shared from the installed app"
+msgstr "无法从已安装的应用中分享此文件"
+
+msgid "Open Kept in Safari to download it."
+msgstr "请在 Safari 中打开 Kept 以下载该文件。"
+
+msgid "Couldn't get the file ready. Try again."
+msgstr "无法准备好文件,请重试。"
+
+msgid "The file is still on its way. Try again in a moment."
+msgstr "文件仍在传输中,请稍后再试。"
+
+msgid "Couldn't share the file. Try again."
+msgstr "无法分享文件。请重试。"
+
+msgid "Kept can't reach its database right now. Try again in a minute."
+msgstr "Kept 暂时无法连接数据库,请稍后再试。"
+
+msgid "{0, plural, one {# day overdue} other {# days overdue}}"
+msgstr "{0, plural, one {已逾期 # 天} other {已逾期 # 天}}"
+
+msgid "{0, plural, one {Every month} other {Every # months}}"
+msgstr "{0, plural, one {每月} other {每 # 个月}}"
+
+msgid "{0} lent out · {1} borrowed · {2} overdue"
+msgstr "{0} 项借出 · {1} 项借入 · {2} 项逾期"
+
+msgid "{0} overdue · {1} due"
+msgstr "{0} 项逾期 · {1} 项到期"
+
+msgid "{0}, {1}"
+msgstr "{0},{1}"
+
+msgid "{days} or at {at}"
+msgstr "{days} 或在 {at}"
+
+msgid "{late, plural, one {# day overdue} other {# days overdue}}"
+msgstr "{late, plural, one {已逾期 # 天} other {已逾期 # 天}}"
+
+msgid "{months, plural, one {Every {every} or # month} other {Every {every} or # months}}"
+msgstr "{months, plural, one {每 {every} 或 # 个月} other {每 {every} 或 # 个月}}"
+
+msgid "{n, plural, one {In # day} other {In # days}}"
+msgstr "{n, plural, one {# 天后} other {# 天后}}"
+
+msgid "{since} to {back} · returned"
+msgstr "{since} 至 {back} · 已归还"
+
+msgid "10% of the interval past the due reading, unless you change it."
+msgstr "除非另有修改,否则默认为超出到期读数间隔的 10%。"
+
+msgid "A date"
+msgstr "日期"
+
+msgid "A new vendor: it's added to your list when you save."
+msgstr "新商家:保存时将自动添加到你的商家列表中。"
+
+msgid "A reading"
+msgstr "一条读数"
+
+msgid "A room or spot, like the kitchen for its boiler, or a thing."
+msgstr "一个房间或点位(如放置锅炉的厨房),或一件物品。"
+
+msgid "A whole number of days."
+msgstr "请输入整数天数。"
+
+msgid "A whole number of months, 1 or more."
+msgstr "请输入大于或等于 1 的整数月数。"
+
+msgid "Add a line"
+msgstr "添加一行"
+
+msgid "Add a service or a check that comes round, like the boiler every year or the car every 10,000 km, and Kept reminds you before it's due."
+msgstr "添加定期维护或检查事项,例如每年检修一次锅炉或汽车每 10,000 公里保养,Kept 会在到期前提醒你。"
+
+msgid "Add line items or an invoice"
+msgstr "添加明细项或发票"
+
+msgid "An owner or admin turns it on in the location's settings, under What to track."
+msgstr "空间所有者或管理员可在空间设置的「追踪内容」中开启此功能。"
+
+msgid "An owner or admin turns them on in the location's settings, under What to track."
+msgstr "所有者或管理员可在空间设置的“追踪内容”中开启这些功能。"
+
+msgid "At {at}"
+msgstr "时间:{at}"
+
+msgid "At most 50 lines."
+msgstr "最多 50 行。"
+
+msgid "Boiler service"
+msgstr "锅炉保养"
+
+msgid "Borrowed from {personLink}"
+msgstr "借自 {personLink}"
+
+msgid "by location"
+msgstr "按空间"
+
+msgid "by person"
+msgstr "按人员"
+
+msgid "by thing or place"
+msgstr "按物品或位置"
+
+msgid "Choose what it's for."
+msgstr "选择其用途。"
+
+msgid "Complete {0}"
+msgstr "完成 {0}"
+
+msgid "Completes"
+msgstr "完成"
+
+msgid "Copy a polite reminder"
+msgstr "复制礼貌提醒话术"
+
+msgid "Cost each"
+msgstr "单价"
+
+msgid "Couldn't complete it"
+msgstr "无法完成"
+
+msgid "Couldn't copy it. Here it is to copy by hand:"
+msgstr "无法自动复制,请手动复制以下内容:"
+
+msgid "Couldn't mark it returned"
+msgstr "无法标记为已归还"
+
+msgid "Couldn't save the service"
+msgstr "无法保存维护记录"
+
+msgid "Couldn't skip it"
+msgstr "无法跳过"
+
+msgid "Couldn't snooze it"
+msgstr "无法推迟提醒"
+
+msgid "Couldn't unsnooze it"
+msgstr "无法取消延后"
+
+msgid "Delete {0}?"
+msgstr "删除 {0}?"
+
+msgid "Direction"
+msgstr "方向"
+
+msgid "Done on"
+msgstr "完成日期"
+
+msgid "Done: {0}"
+msgstr "已完成:{0}"
+
+msgid "Due"
+msgstr "应还 / 到期"
+
+msgid "Due {day}"
+msgstr "到期时间:{day}"
+
+msgid "Due on"
+msgstr "到期日"
+
+msgid "Due today"
+msgstr "今日到期"
+
+msgid "Enter a number, like 10000."
+msgstr "请输入数字,例如 10000。"
+
+msgid "Enter a number, like 2 or 380."
+msgstr "输入数字,例如 2 或 380。"
+
+msgid "Enter a number, like 60250."
+msgstr "输入数字,例如 60250。"
+
+msgid "Every … {0}"
+msgstr "每隔… {0}"
+
+msgid "Every … months"
+msgstr "每隔 … 个月"
+
+msgid "Every {every}"
+msgstr "每 {every}"
+
+msgid "Fluid"
+msgstr "油液"
+
+msgid "For"
+msgstr "用途"
+
+msgid "Give it a name, like \"Boiler service\"."
+msgstr "起一个名字,例如「锅炉保养」。"
+
+msgid "Has from us"
+msgstr "借有我们的物品"
+
+msgid "Hi {person}, a friendly reminder about the {thing} I lent you on {since}. Could you bring it back when you're done with it? Thank you!"
+msgstr "嗨 {person},温馨提醒一下:我在 {since} 借给你的「{thing}」,用完后麻烦还给我哦,谢谢!"
+
+msgid "Hi {person}, a friendly reminder about the {thing} I lent you on {since}. It was due back on {due}. Could you bring it back when you can? Thank you!"
+msgstr "嗨 {person},温馨提醒一下:我在 {since} 借给你的「{thing}」原定于 {due} 归还。方便的时候麻烦还给我哦,谢谢!"
+
+msgid "In: borrowed"
+msgstr "借入:待归还"
+
+msgid "Its reminders stop. The services it recorded stay on their thing or place."
+msgstr "其提醒将停止。已记录的维护历史仍会保留在对应的物品或位置上。"
+
+msgid "Labour"
+msgstr "人工费"
+
+msgid "Last done"
+msgstr "上次完成"
+
+msgid "Last done {day}"
+msgstr "上次完成:{day}"
+
+msgid "Latest first"
+msgstr "最新优先"
+
+msgid "Lend a thing from its page, and it shows here with who has it and when it's due back."
+msgstr "在物品页面中记录借出后,这里会显示借用人及应归还日期。"
+
+msgid "Lending is off in your locations"
+msgstr "你的空间未开启借出功能"
+
+msgid "Lent to {personLink}"
+msgstr "已借给 {personLink}"
+
+msgid "Lent to us"
+msgstr "借入"
+
+msgid "Line {0}"
+msgstr "第 {0} 行"
+
+msgid "Line items"
+msgstr "明细行"
+
+msgid "Loading loans"
+msgstr "正在加载借出记录"
+
+msgid "Loans"
+msgstr "借出记录"
+
+msgid "Loans with {name} that ended"
+msgstr "与 {name} 已结束的借出记录"
+
+msgid "Log a service"
+msgstr "记录保养服务"
+
+msgid "Mark returned"
+msgstr "标记为已归还"
+
+msgid "Needs a connection: completing, snoozing and changing schedules wait until you're back online."
+msgstr "需要联网:完成、延后和修改计划等操作将在恢复网络后生效。"
+
+msgid "Needs a connection: it has money. A reading alone can be logged offline."
+msgstr "需要联网:此记录包含金额。仅记录表计读数可离线保存。"
+
+msgid "Needs a connection: marking things returned waits until you're back online."
+msgstr "需要联网:标记物品已归还将在恢复网络后生效。"
+
+msgid "New schedule"
+msgstr "新建计划"
+
+msgid "No due date yet"
+msgstr "暂未设置到期日"
+
+msgid "No match: this name is added as a new vendor"
+msgstr "无匹配项:该名称将作为新供应商添加"
+
+msgid "Not done this time"
+msgstr "本次未完成"
+
+msgid "Not in the future."
+msgstr "不能晚于今天。"
+
+msgid "Nothing lent or borrowed"
+msgstr "暂无借出或借入记录"
+
+msgid "Nothing scheduled"
+msgstr "暂无计划任务"
+
+msgid "Once"
+msgstr "仅一次"
+
+msgid "Once, on {day}"
+msgstr "单次,{day}"
+
+msgid "Optional: count on a meter too, whichever comes first."
+msgstr "可选:也可同时按表计计数,以先到者为准。"
+
+msgid "Optional."
+msgstr "选填。"
+
+msgid "Optional. Checked against the readings before and after it."
+msgstr "选填。将结合前后读数进行校验。"
+
+msgid "Optional. It was due at {dueAt}."
+msgstr "可选。原定应于 {dueAt} 到期。"
+
+msgid "Optional. Pick one, or type a new name."
+msgstr "可选。从列表选择,或输入新名称。"
+
+msgid "Optional. The count starts here; today if you leave it."
+msgstr "可选。清点将从此日开始;留空则从今天开始。"
+
+msgid "Out now"
+msgstr "当前借出"
+
+msgid "Out: lent"
+msgstr "已借出"
+
+msgid "Overdue"
+msgstr "已逾期"
+
+msgid "Part"
+msgstr "配件"
+
+msgid "Photo added"
+msgstr "已添加照片"
+
+msgid "Photo of the meter"
+msgstr "表计照片"
+
+msgid "Photo or file"
+msgstr "照片或文件"
+
+msgid "Pick a day after today."
+msgstr "请选择今天之后的日期。"
+
+msgid "Pick the day it was done."
+msgstr "选择完成的日期。"
+
+msgid "Pick the day it's due."
+msgstr "选择到期日期。"
+
+msgid "Remind me, days before"
+msgstr "提前提醒天数"
+
+msgid "Reminder copied"
+msgstr "已复制提醒"
+
+msgid "Remove {0}"
+msgstr "移除 {0}"
+
+msgid "Remove this line"
+msgstr "移除此行"
+
+msgid "Repeats"
+msgstr "重复周期"
+
+msgid "Replace the photo"
+msgstr "替换照片"
+
+msgid "Returned"
+msgstr "已归还"
+
+msgctxt "loan"
+msgid "Returned"
+msgstr "已归还"
+
+msgid "Saved {0}"
+msgstr "已保存 {0}"
+
+msgid "Saving restarts its count"
+msgstr "保存后将重新开始计数"
+
+msgid "Say what it was."
+msgstr "说明这是什么。"
+
+msgid "Schedules are off in your locations"
+msgstr "你的空间均已关闭计划功能"
+
+msgid "Search by name or thing"
+msgstr "按名称或物品搜索"
+
+msgid "Search by thing or person"
+msgstr "按物品或人员搜索"
+
+msgid "Search loans"
+msgstr "搜索借出记录"
+
+msgid "Search rooms, spots and things"
+msgstr "搜索房间、点位和物品"
+
+msgid "Search schedules"
+msgstr "搜索计划"
+
+msgid "Send it however you like. Kept never sends it."
+msgstr "请按你喜欢的方式发送,Kept 不会代发。"
+
+msgid "Service logged"
+msgstr "已记录维护保养"
+
+msgid "Set how often: every so many months or units, or a date."
+msgstr "设置频率:每隔几个月、每隔多少单位,或指定日期。"
+
+msgid "Since"
+msgstr "起始时间"
+
+msgid "Since {since} · due {due}"
+msgstr "自 {since} · 到期:{due}"
+
+msgid "Since {since} · no due date"
+msgstr "始于 {since} · 无截止日期"
+
+msgid "Skip once"
+msgstr "跳过本次"
+
+msgid "Skipping {0} once"
+msgstr "本次跳过 {0}"
+
+msgid "Skipping once"
+msgstr "本次跳过"
+
+msgid "Snooze"
+msgstr "延后提醒"
+
+msgid "Snooze {0}"
+msgstr "延后 {0}"
+
+msgid "Snooze until"
+msgstr "延后至"
+
+msgid "Snooze until, {0}"
+msgstr "推迟至,{0}"
+
+msgid "Snoozed until {at}"
+msgstr "已延后至 {at}"
+
+msgid "Snoozed until {day}"
+msgstr "已延后至 {day}"
+
+msgid "Snoozed until {said}"
+msgstr "已延后至 {said}"
+
+msgid "Soonest first"
+msgstr "最早到期优先"
+
+msgid "The invoice didn't attach. Add it again from the service."
+msgstr "发票未能附上。请从该保养记录中重新添加。"
+
+msgid "The lines add up to {0}; that's the total unless you type one."
+msgstr "各明细行总计 {0};除非手动输入总金额,否则将以此为准。"
+
+msgid "The lines add up to {0}. Check the total or the lines."
+msgstr "各明细行总计为 {0}。请核对总金额或各项明细。"
+
+msgid "the thing"
+msgstr "该物品"
+
+msgid "Thing or place"
+msgstr "物品或位置"
+
+msgid "Unsnooze"
+msgstr "取消延后"
+
+msgid "Unsnoozed {0}"
+msgstr "已取消延后 {0}"
+
+msgid "Until"
+msgstr "截止日期"
+
+msgid "Upcoming"
+msgstr "即将到期"
+
+msgid "What"
+msgstr "事项"
+
+msgid "What {name} has from us"
+msgstr "{name} 从我们这里借走的物品"
+
+msgid "What {name} lent us"
+msgstr "{name} 借给我们的物品"
+
+msgid "{earlier, plural, one {# earlier term} other {# earlier terms}}"
+msgstr "{earlier, plural, one {# 个更早期限} other {# 个更早期限}}"
+
+msgid "{name}, file {0}"
+msgstr "{name},文件 {0}"
+
+msgid "{title} for {0}"
+msgstr "{0} 的{title}"
+
+msgid "A whole number of days, from 0 to {max}."
+msgstr "请输入 0 到 {max} 之间的整数天数。"
+
+msgid "A word inside, or what it's for"
+msgstr "内部词条或用途说明"
+
+msgid "Add document"
+msgstr "添加文档"
+
+msgid "Add expiring document"
+msgstr "添加含有效期的文档"
+
+msgid "All of it in Paperwork"
+msgstr "全部收于文档资料"
+
+msgid "Borrowed in"
+msgstr "已借入"
+
+msgid "by state"
+msgstr "按状态"
+
+msgid "Card cover"
+msgstr "卡片封面"
+
+msgid "Contract"
+msgstr "合同"
+
+msgid "Due at {value} {unit}"
+msgstr "到期阈值:{value} {unit}"
+
+msgid "Due back {day}"
+msgstr "应还日期:{day}"
+
+msgid "Expired {day}"
+msgstr "已于 {day} 过期"
+
+msgid "Expires {day}"
+msgstr "到期日:{day}"
+
+msgid "Expiring document for {subjectName}"
+msgstr "{subjectName} 的文档即将到期"
+
+msgid "Expiry"
+msgstr "到期时间"
+
+msgid "Extended warranty"
+msgstr "延保服务"
+
+msgid "File {0}"
+msgstr "文件 {0}"
+
+msgid "First term"
+msgstr "首期保修"
+
+msgid "grid"
+msgstr "网格"
+
+msgid "Grid"
+msgstr "网格"
+
+msgid "Inspection"
+msgstr "检查"
+
+msgid "Insurance"
+msgstr "保险"
+
+msgid "Insurance cover"
+msgstr "保险保障"
+
+msgid "Its reminders stop. You can undo this for 7 days."
+msgstr "其提醒将停止。7 天内可撤销此操作。"
+
+msgid "Keep the name under {0} characters."
+msgstr "名称请勿超过 {0} 个字符。"
+
+msgid "Later"
+msgstr "稍后"
+
+msgid "Lease"
+msgstr "租赁"
+
+msgid "Lent out"
+msgstr "已借出"
+
+msgid "Licence"
+msgstr "许可证"
+
+msgid "Like Home insurance, or the flat's lease"
+msgstr "例如:房屋保险、公寓租约"
+
+msgid "Maker's warranty"
+msgstr "原厂保修"
+
+msgid "Name it, like Building inspection."
+msgstr "起个名字,例如「房屋巡检」。"
+
+msgid "New term runs out on"
+msgstr "新周期到期日"
+
+msgid "No documents for <0>{0}0> yet: the lease or the deed, the home insurance, utility contracts."
+msgstr "<0>{0}0> 暂无文档:例如租约或房产证、房屋保险、水电燃气合同。"
+
+msgid "No documents in <0>{0}0> yet: the manual of a built-in oven, the boiler's certificate."
+msgstr "<0>{0}0> 暂无文档:例如嵌入式烤箱说明书、锅炉检验证书。"
+
+msgid "Nothing runs out soon"
+msgstr "近期没有即将到期的事项"
+
+msgid "Open {what}"
+msgstr "打开 {what}"
+
+msgid "Open Lending"
+msgstr "打开借出管理"
+
+msgid "Open Schedules"
+msgstr "打开计划"
+
+msgid "Paperwork is off in every location. An admin turns it on in What to track."
+msgstr "所有空间均未开启单据文书功能。管理员可在“追踪内容”中开启。"
+
+msgid "Paperwork of {0}"
+msgstr "{0} 的文档资料"
+
+msgid "Pick the day it runs out."
+msgstr "选择到期的日期。"
+
+msgid "Pick the day the new term runs out."
+msgstr "选择新期限到期的日期。"
+
+msgid "Ran out"
+msgstr "已到期"
+
+msgid "Ran out {day}"
+msgstr "已于 {day} 到期"
+
+msgid "Receipts, manuals and warranty cards added to things, and the lease or insurance added to a location or a room, all show here."
+msgstr "添加到物品的收据、说明书和保修卡,以及添加到空间或房间的租约与保单,都会汇总显示在这里。"
+
+msgid "Register the warranty by {day}"
+msgstr "请在 {day} 前注册保修"
+
+msgid "Remove {name}?"
+msgstr "移除 {name}?"
+
+msgid "Removed {name}"
+msgstr "已移除 {name}"
+
+msgid "Renew"
+msgstr "续期"
+
+msgid "Renew {name}"
+msgstr "续期 {name}"
+
+msgid "Renewed {name}"
+msgstr "已续期 {name}"
+
+msgid "Runs out {day}"
+msgstr "耗尽于 {day}"
+
+msgid "Runs out on"
+msgstr "到期日"
+
+msgid "Runs out soon"
+msgstr "即将用完"
+
+msgid "Search your paperwork"
+msgstr "搜索你的文档资料"
+
+msgid "Share {what}"
+msgstr "共享 {what}"
+
+msgid "Store warranty"
+msgstr "保存保修信息"
+
+msgid "The new term has to end after the current one."
+msgstr "新期限的结束日期必须晚于当前期限。"
+
+msgid "The old term stays in its history."
+msgstr "旧保修期限会保留在历史记录中。"
+
+msgid "Things that expire"
+msgstr "会过期的物品"
+
+msgid "This document was renewed or removed since. Refresh to see it now."
+msgstr "该文档此后已被更新或移除。刷新以查看最新状态。"
+
+msgid "Warranties"
+msgstr "保修"
+
+msgid "Warranties, documents like the lease or the home insurance, and things with an expiry date show here, soonest first."
+msgstr "保修、租约或房屋保险等文档以及带到期日的物品会按到期先后顺序显示在这里。"
+
+msgid "Warranty ends {day}"
+msgstr "保修到期:{day}"
+
+msgid "Whole locations"
+msgstr "整个空间"
+
+msgid "{0, plural, one {# document} other {# documents}}"
+msgstr "{0, plural, one {# 份文档} other {# 份文档}}"
+
+msgid "{0, plural, one {# year} other {# years}}"
+msgstr "{0, plural, one {# 年} other {# 年}}"
+
+msgid "{0} · overdue"
+msgstr "{0} · 已逾期"
+
+msgid "{0} from {started}"
+msgstr "{0}(自 {started} 起)"
+
+msgid "{0}: {1} (from the brand)"
+msgstr "{0}:{1}(来自品牌方)"
+
+msgid "{0}: {1} (from the type)"
+msgstr "{0}:{1}(继承自类型)"
+
+msgid "{0}: a closed claim reopens only with Undo, from its history."
+msgstr "{0}:已关闭的理赔只能通过历史记录中的“撤销”重新打开。"
+
+msgid "{count, plural, one {the only valuation} other {latest of # valuations}}"
+msgstr "{count, plural, one {唯一一次估值} other {共 # 次估值中的最新一次}}"
+
+msgid "{months, plural, one {# month} other {# months}}"
+msgstr "{months, plural, one {# 个月} other {# 个月}}"
+
+msgid "{n, plural, one {Due in # day} other {Due in # days}}"
+msgstr "{n, plural, one {还有 # 天到期} other {还有 # 天到期}}"
+
+msgid "{source} by <0>{by}0> · {on} · {latestOf}"
+msgstr "{source} 由 <0>{by}0> 提供 · {on} · {latestOf}"
+
+msgid "+ New person: {typed}"
+msgstr "+ 新建联系人:{typed}"
+
+msgid "<0>{0}0>, where it was"
+msgstr "原位于 <0>{0}0>"
+
+msgid "A borrowed thing"
+msgstr "借入的物品"
+
+msgid "A claim needs the day it was opened."
+msgstr "发起理赔需填写提交日期。"
+
+msgid "A new person: added to your people when you save. Kept never contacts them."
+msgstr "新联系人:保存时会添加到你的联系人列表中。Kept 绝不会主动联系他们。"
+
+msgid "A phone number, an email or a web page."
+msgstr "电话号码、邮箱地址或网页链接。"
+
+msgid "A service or a check that comes round: Kept reminds you before it's due."
+msgstr "定期进行的保养或检查:Kept 会在到期前提醒你。"
+
+msgid "A term"
+msgstr "条款"
+
+msgid "A value needs a currency."
+msgstr "估值需要指定货币。"
+
+msgid "A value needs a date."
+msgstr "估值需要填写日期。"
+
+msgid "A warranty covers one thing: split this one first to add one."
+msgstr "一份保修只能对应一件物品:请先拆分此物品再添加保修。"
+
+msgid "A warranty needs a start date."
+msgstr "保修需要填写开始日期。"
+
+msgid "A whole number of months, from 1 to 600."
+msgstr "请输入 1 到 600 之间的整数月数。"
+
+msgid "Add a valuation"
+msgstr "添加估值"
+
+msgid "Add a warranty"
+msgstr "添加保修"
+
+msgid "An end date on or after the start."
+msgstr "结束日期不得早于开始日期。"
+
+msgid "An estimate, an appraisal or the insurer's figure: the latest one is its value."
+msgstr "估算值、评估价或保险公司定损额:以最新一条作为当前估值。"
+
+msgid "Appraisal"
+msgstr "专业估价"
+
+msgid "At"
+msgstr "于"
+
+msgid "At <0>{0}0>"
+msgstr "位于 <0>{0}0>"
+
+msgid "Attach a job card or photo"
+msgstr "附加维修单或照片"
+
+msgid "Attach the card or certificate"
+msgstr "附上保修卡或凭证"
+
+msgid "Back from {0}"
+msgstr "归还自 {0}"
+
+msgid "Borrowed"
+msgstr "已借入"
+
+msgid "Borrowed from"
+msgstr "借自"
+
+msgid "Borrowed from {0}"
+msgstr "借自 {0}"
+
+msgid "Borrowed thing"
+msgstr "借入物品"
+
+msgid "Bought {0} for {1}"
+msgstr "以 {1} 购入 {0}"
+
+msgid "Bought {0} for {1}, <0>{2}0>"
+msgstr "购于 {0},价格 {1},<0>{2}0>"
+
+msgid "Change the due date"
+msgstr "更改到期日期"
+
+msgid "Choose where it goes."
+msgstr "选择目标位置。"
+
+msgid "Claim contact"
+msgstr "理赔联系人"
+
+msgid "Claim details"
+msgstr "理赔详情"
+
+msgid "Claim opened"
+msgstr "已提交理赔"
+
+msgid "Claim progress"
+msgstr "理赔进度"
+
+msgid "Claim removed"
+msgstr "理赔已移除"
+
+msgid "Claim saved"
+msgstr "理赔已保存"
+
+msgid "Claim: {0}"
+msgstr "理赔:{0}"
+
+msgid "Claims"
+msgstr "理赔"
+
+msgid "Claims · {0}"
+msgstr "理赔 · {0}"
+
+msgid "claims:"
+msgstr "申请理赔:"
+
+msgid "Clear it for no due date."
+msgstr "清空表示无到期日。"
+
+msgid "Closed on"
+msgstr "关闭日期"
+
+msgid "Condition at lending"
+msgstr "借出时状况"
+
+msgid "Condition photos"
+msgstr "成色照片"
+
+msgid "contact, no account"
+msgstr "仅联系人,无账号"
+
+msgid "Covered by the warranty"
+msgstr "在保修范围内"
+
+msgid "Covered for life, from {from}"
+msgstr "终身保障,自 {from} 起"
+
+msgid "Covered from {from} to {until}; today is {pct} of the way"
+msgstr "保障期从 {from} 至 {until};目前已过 {pct}"
+
+msgid "Covered to {0}"
+msgstr "保障至 {0}"
+
+msgid "Covered until"
+msgstr "有效期至"
+
+msgid "Credit card cover"
+msgstr "信用卡附带保障"
+
+msgid "current"
+msgstr "当前"
+
+msgid "Document {0}"
+msgstr "文档 {0}"
+
+msgid "Due back"
+msgstr "应归还日期"
+
+msgid "Due date changed"
+msgstr "到期日已更改"
+
+msgid "Edit the valuation"
+msgstr "编辑估值"
+
+msgid "Edit the warranty"
+msgstr "编辑保修"
+
+msgid "Ended {0}"
+msgstr "已于 {0} 结束"
+
+msgid "Ends {0}"
+msgstr "到期时间:{0}"
+
+msgid "Estimate"
+msgstr "估算"
+
+msgid "For a claim recorded by mistake. You can undo this for 7 days."
+msgstr "用于误录的理赔记录。7 天内可撤销此操作。"
+
+msgid "For a loan recorded by mistake: it's as if it never happened. You can undo this for 7 days."
+msgstr "适用于误记的借出记录:删除后如同从未借出。7 天内可撤销此操作。"
+
+msgid "for life, from {started}"
+msgstr "终身有效,自 {started} 起"
+
+msgid "from {started}"
+msgstr "自 {started} 起"
+
+msgid "From {who} since {since}"
+msgstr "自 {since} 起由 {who} 借出"
+
+msgid "From {who} since {since} · due back {due}"
+msgstr "自 {since} 借自 {who} · 应还日期 {due}"
+
+msgid "From the purchase date; change it if it started later."
+msgstr "默认从购买日期起算;如晚于该日期开始,请修改。"
+
+msgid "Give it back to {0}"
+msgstr "归还给 {0}"
+
+msgid "Given back to {0}"
+msgstr "已归还给 {0}"
+
+msgid "Gone for repair"
+msgstr "已送修"
+
+msgid "How long"
+msgstr "时长"
+
+msgid "How many"
+msgstr "数量"
+
+msgid "In repair"
+msgstr "维修中"
+
+msgid "Insurer's value"
+msgstr "保险公司估值"
+
+msgid "It belongs to {0}: it leaves your counts and totals, and stays in its history."
+msgstr "它属于 {0}:将从你的数量和总额中移除,并保留在历史记录中。"
+
+msgid "It's in repair: lend it once it's back."
+msgstr "该物品正在维修中:归还后再行借出。"
+
+msgid "Kept never contacts them."
+msgstr "Kept 绝不会向他们发送任何信息。"
+
+msgid "Kept never messages {0}; the reminder text is yours to send."
+msgstr "Kept 不会主动向 {0} 发送消息,请由你自行发送提醒内容。"
+
+msgid "Kept reminds you on {0}. It never messages {1}; the reminder text is yours to send."
+msgstr "Kept 会在 {0} 提醒你,绝不会向 {1} 发送消息;提醒内容由你自行发送。"
+
+msgid "Lend"
+msgstr "借出"
+
+msgid "Lend {0}"
+msgstr "借出 {0}"
+
+msgid "Lend it to a member or a contact, with a due date if you like."
+msgstr "可借给成员或联系人,也可按需设置应还日期。"
+
+msgid "Lend to"
+msgstr "借给"
+
+msgid "Lent by"
+msgstr "出借人"
+
+msgid "Lent to"
+msgstr "借给"
+
+msgid "Lent to {0}"
+msgstr "已借给 {0}"
+
+msgid "Lifetime"
+msgstr "终身"
+
+msgid "Loading the claims"
+msgstr "正在加载理赔记录"
+
+msgid "Loading the defaults"
+msgstr "正在加载默认模板"
+
+msgid "Loading the loans"
+msgstr "正在加载借出记录"
+
+msgid "Loading the schedules"
+msgstr "正在加载计划"
+
+msgid "Loading the value"
+msgstr "正在加载估值"
+
+msgid "Loading the warranties"
+msgstr "正在加载保修信息"
+
+msgid "Loan"
+msgstr "借出记录"
+
+msgid "Loan removed"
+msgstr "借出记录已移除"
+
+msgid "Loans · {0} open"
+msgstr "借出记录 · {0} 项未还"
+
+msgid "Longest cover"
+msgstr "最长保障期限"
+
+msgid "Manufacturer warranty"
+msgstr "原厂保修"
+
+msgid "Member of this location"
+msgstr "此空间的成员"
+
+msgid "Months"
+msgstr "个月"
+
+msgid "New claim"
+msgstr "新建理赔"
+
+msgid "No claims"
+msgstr "暂无理赔记录"
+
+msgid "No default term on this brand or type."
+msgstr "此品牌或类型未设置默认保修期。"
+
+msgid "No photos."
+msgstr "暂无照片。"
+
+msgid "No value recorded"
+msgstr "暂无估值记录"
+
+msgid "No warranties yet"
+msgstr "暂无保修记录"
+
+msgid "No warranty"
+msgstr "无保修"
+
+msgid "Not lent out"
+msgstr "未借出"
+
+msgid "Not registered yet · register by {deadline}"
+msgstr "尚未注册 · 请于 {deadline} 前注册"
+
+msgid "Of {0}. Lending some splits them off; they merge back when returned."
+msgstr "共 {0} 件。借出部分数量时会自动拆分,归还后再合并。"
+
+msgid "On loan"
+msgstr "已借出"
+
+msgid "Open the claim"
+msgstr "打开理赔"
+
+msgid "Opened"
+msgstr "已打开"
+
+msgid "Opened {0}"
+msgstr "已开封 {0}"
+
+msgid "Optional. Kept reminds you before this day."
+msgstr "可选。Kept 会在该日期前提醒你。"
+
+msgid "Optional. Kept reminds you when it's due back."
+msgstr "可选。Kept 会在应归还时提醒你。"
+
+msgid "Optional. Shown as \"Warranty saved you\" when the repair cost nothing."
+msgstr "可选。当维修费用为零时,将显示为「保修为你省下」。"
+
+msgid "Paperwork and warranties"
+msgstr "单据与保修"
+
+msgid "Purchase price"
+msgstr "购买价格"
+
+msgid "Put them back with the rest"
+msgstr "放回原处与其他物品一起"
+
+msgid "Recorded by"
+msgstr "记录人"
+
+msgid "Reference"
+msgstr "参考"
+
+msgid "Register by"
+msgstr "注册截止日期"
+
+msgid "Registered with the maker"
+msgstr "已向制造商注册"
+
+msgctxt "claim status"
+msgid "Rejected"
+msgstr "已拒绝"
+
+msgid "Rejected {0}"
+msgstr "已拒绝 {0}"
+
+msgid "Remove this claim?"
+msgstr "移除此理赔记录?"
+
+msgid "Remove this loan"
+msgstr "删除此借出记录"
+
+msgid "Remove this loan?"
+msgstr "删除此借出记录?"
+
+msgid "Remove this valuation?"
+msgstr "移除此估值?"
+
+msgid "Remove this warranty?"
+msgstr "要移除此保修吗?"
+
+msgid "Resolved {0}"
+msgstr "已解决 {0}"
+
+msgid "Returned late"
+msgstr "逾期归还"
+
+msgid "Returns to"
+msgstr "归还至"
+
+msgid "Somewhere else"
+msgstr "其他地方"
+
+msgid "Starts"
+msgstr "开始"
+
+msgid "Still here"
+msgstr "仍在原处"
+
+msgid "The brand's claim page"
+msgstr "品牌官方理赔页面"
+
+msgid "The maker, the shop or the insurer."
+msgstr "制造商、商家或保险公司。"
+
+msgid "The maker's, the shop's, an extended one: each with its own end date."
+msgstr "原厂保修、商家保修、延保服务:各自拥有独立的截止日期。"
+
+msgid "The one that covers longest."
+msgstr "覆盖期限最长的一项。"
+
+msgid "The value falls back to the one before it. You can undo this for 7 days."
+msgstr "估值将回退到上一条记录。7 天内可撤销此操作。"
+
+msgid "Type (optional)"
+msgstr "类型(可选)"
+
+msgid "Update"
+msgstr "更新"
+
+msgid "Update the claim"
+msgstr "更新理赔"
+
+msgid "uses Kept"
+msgstr "使用 Kept"
+
+msgid "Uses Kept"
+msgstr "使用 Kept"
+
+msgid "Usually in"
+msgstr "常放于"
+
+msgid "Valuation added"
+msgstr "已添加估值"
+
+msgid "Valuation removed"
+msgstr "估值已移除"
+
+msgid "Valuation saved"
+msgstr "已保存估值"
+
+msgid "Valuations"
+msgstr "估值"
+
+msgid "Value"
+msgstr "价值"
+
+msgid "Valued on"
+msgstr "估值日期"
+
+msgid "Warranties · {0}"
+msgstr "保修 · {0}"
+
+msgid "Warranty added"
+msgstr "已添加保修"
+
+msgid "Warranty contact:"
+msgstr "保修联系人:"
+
+msgid "Warranty removed"
+msgstr "已移除保修"
+
+msgid "Warranty saved"
+msgstr "保修已保存"
+
+msgid "Warranty saved you {saved}"
+msgstr "保修已为你节省 {saved}"
+
+msgid "What is it called?"
+msgstr "它叫什么名称?"
+
+msgid "What it would have cost"
+msgstr "原本应支付的费用"
+
+msgid "What you paid"
+msgstr "你的实付金额"
+
+msgid "What's wrong"
+msgstr "问题详情"
+
+msgid "When it breaks, open a claim: Kept fills in the warranty that covers longest and remembers where it went for repair."
+msgstr "物品损坏时可发起理赔:Kept 会自动填入覆盖时间最长的保修,并记录物品寄修的地点。"
+
+msgid "Where it goes"
+msgstr "去向"
+
+msgid "Where it is now"
+msgstr "当前位置"
+
+msgid "Where it usually is"
+msgstr "常放位置"
+
+msgid "Where it was"
+msgstr "原位置"
+
+msgid "Where to claim"
+msgstr "理赔渠道"
+
+msgid "Who is it going to?"
+msgstr "要借给谁?"
+
+msgid "Who lent it to you?"
+msgstr "从谁那里借来的?"
+
+msgid "With {who} since {since}"
+msgstr "自 {since} 起由 {who} 持有"
+
+msgid "With {who} since {since} · due {due}"
+msgstr "自 {since} 由 {who} 持有 · 应还 {due}"
+
+msgid "search word ({language})"
+msgstr "搜索关键词({language})"
+
+msgid "Details need a connection."
+msgstr "查看详情需要联网。"
+
+msgid "From {who}"
+msgstr "来自 {who}"
+
+msgid "From {who} · due back {due}"
+msgstr "借自 {who} · 应还日期 {due}"
+
+msgid "Inside {0}"
+msgstr "位于 {0} 内"
+
+msgid "It isn't in this phone's copy. It opens when you're back online."
+msgstr "此项未包含在这台手机的离线副本中,重新联网后即可打开。"
+
+msgid "Nothing here in this phone's copy."
+msgstr "此手机的离线副本中没有任何内容。"
+
+msgid "Places in {name}"
+msgstr "{name} 中的位置"
+
+msgid "Things in {name}"
+msgstr "{name} 中的物品"
+
+msgid "With {who}"
+msgstr "在 {who} 处"
+
+msgid "With {who} · due {due}"
+msgstr "借给 {who} · 应还日期 {due}"
+
+msgid "{browser} on {os}"
+msgstr "{os} 上的 {browser}"
+
+msgid "{MAX_CALENDAR_FEEDS, plural, one {# link is the most. Revoke one to make another.} other {# links are the most. Revoke one to make another.}}"
+msgstr "{MAX_CALENDAR_FEEDS, plural, one {最多可创建 # 个链接。请先撤销一个再创建新链接。} other {最多可创建 # 个链接。请先撤销一个再创建新链接。}}"
+
+msgid "{MAX_WEBHOOK_CHANNELS, plural, one {You have # webhook, the most Kept allows.} other {You have # webhooks, the most Kept allows.}}"
+msgstr "{MAX_WEBHOOK_CHANNELS, plural, one {你已创建 # 个 Webhook,已达 Kept 上限。} other {你已创建 # 个 Webhook,已达 Kept 上限。}}"
+
+msgid "{unreadText} unread"
+msgstr "{unreadText} 条未读"
+
+msgid "{who} joined {where}"
+msgstr "{who} 加入了 {where}"
+
+msgid "{who} no longer has access to {where}"
+msgstr "{who} 已失去对 {where} 的访问权限"
+
+msgid "A device"
+msgstr "一台设备"
+
+msgid "A private link your calendar app subscribes to: what's due and what runs out, as all-day events, from a month back to 13 months ahead. Titles and dates only, never money."
+msgstr "供日历应用订阅的私密链接:将到期事项与耗材提醒以全天日程形式展示(涵盖过去 1 个月至未来 13 个月)。仅包含标题与日期,绝不包含金额。"
+
+msgid "Add a webhook"
+msgstr "添加 Webhook"
+
+msgid "AI monthly summary"
+msgstr "AI 月度汇总"
+
+msgid "AI reached this month's cap"
+msgstr "AI 已达到本月限额"
+
+msgid "AI spending caps"
+msgstr "AI 消费上限"
+
+msgid "AI used 80% of this month's cap"
+msgstr "本月 AI 用量已达上限的 80%"
+
+msgid "Allow notifications for Kept in this browser's settings, then try again."
+msgstr "请在当前浏览器的设置中允许 Kept 发送通知,然后再试。"
+
+msgid "Browser"
+msgstr "浏览器"
+
+msgid "Calendar feed"
+msgstr "日历订阅源"
+
+msgid "Calendar links"
+msgstr "日历链接"
+
+msgid "Calendars subscribed to it stop updating. A new link can be made any time."
+msgstr "订阅该链接的日历将停止更新。你可随时生成新链接。"
+
+msgid "Checked {at} · {n} new"
+msgstr "检查于 {at} · {n} 封新邮件"
+
+msgid "Complete {heading}"
+msgstr "完成{heading}"
+
+msgid "Copy a reminder"
+msgstr "复制提醒文案"
+
+msgid "Copy a reminder for {heading}"
+msgstr "复制 {heading} 的提醒"
+
+msgid "Copy the link"
+msgstr "复制链接"
+
+msgid "Copy the link now"
+msgstr "立即复制链接"
+
+msgid "Copy the secret"
+msgstr "复制密钥"
+
+msgid "Copy the signing secret now"
+msgstr "立即复制签名密钥"
+
+msgid "Couldn't create a link"
+msgstr "无法创建链接"
+
+msgid "Couldn't mark it read"
+msgstr "无法标记为已读"
+
+msgid "Couldn't revoke it"
+msgstr "无法撤销"
+
+msgid "Couldn't save that"
+msgstr "无法保存"
+
+msgid "Couldn't send a test"
+msgstr "无法发送测试请求"
+
+msgid "Couldn't turn notifications on"
+msgstr "无法开启通知"
+
+msgid "Couldn't turn them off"
+msgstr "无法关闭"
+
+msgid "Create a link"
+msgstr "创建链接"
+
+msgid "Daily digest"
+msgstr "每日摘要"
+
+msgid "Digest and quiet hours"
+msgstr "汇总推送与免打扰时段"
+
+msgid "Documents running out"
+msgstr "即将到期的文档"
+
+msgid "Downloads"
+msgstr "下载"
+
+msgid "Due and coming up"
+msgstr "已到期及即将到期"
+
+msgid "Due at {value}"
+msgstr "到期读数:{value}"
+
+msgid "Email and the notification centre still reach you."
+msgstr "电子邮件和通知中心仍可送达。"
+
+msgid "Enter the full address, starting with https://"
+msgstr "请输入完整地址,以 https:// 开头"
+
+msgid "Everything lands in the notification centre. These reach you outside Kept as well."
+msgstr "所有消息都会进入通知中心。以下渠道还会在 Kept 之外提醒你。"
+
+msgid "Failed jobs shows why it stopped; if the worker isn't running, start it again. The next good check resolves this alert."
+msgstr "“失败任务”中会显示停止原因;如果后台进程未运行,请重新启动。下次检查正常后,此告警将自动解除。"
+
+msgid "Failing since {since}"
+msgstr "自 {since} 起持续失败"
+
+msgid "For your own automations: Kept posts a signed message when something is due, with ids and dates only, never names."
+msgstr "供你自行接入自动化:当有事项到期时,Kept 会发送带签名的消息,仅含 ID 与日期,不包含名称。"
+
+msgid "How to install"
+msgstr "安装指南"
+
+msgid "In Kept"
+msgstr "在 Kept 中"
+
+msgid "It answered {code}."
+msgstr "返回状态码 {code}。"
+
+msgid "It couldn't be reached."
+msgstr "无法连接。"
+
+msgid "It's no longer there."
+msgstr "它已不在那里了。"
+
+msgid "Kept last checked for due reminders {lastOk}. Until it checks again, nobody gets new reminders."
+msgstr "Kept 上次检查到期提醒是在 {lastOk}。在下次检查完成前,任何人都不会收到新的提醒。"
+
+msgid "Kept sends at most 5 tests an hour, across all your channels and devices. Try again later."
+msgstr "Kept 每小时最多在所有渠道和设备间发送 5 次测试,请稍后再试。"
+
+msgid "Kept shows it only this once. Anyone with it can read the titles and dates."
+msgstr "Kept 仅显示这一次。任何持有该链接的人都可以查看标题和日期。"
+
+msgid "Kept shows it only this once. Your receiver checks each message's Kept-Signature header with it."
+msgstr "Kept 仅显示这一次。你的接收端需使用它校验每条消息的 Kept-Signature 请求头。"
+
+msgid "Kept stops posting to it. Its secret can't be used again."
+msgstr "Kept 将停止向其推送,其密钥也将作废。"
+
+msgid "Last fetched {fetched}"
+msgstr "上次拉取于 {fetched}"
+
+msgid "Last month's AI use, sent to your email."
+msgstr "上月的 AI 用量已发送至你的邮箱。"
+
+msgid "Link made {made}"
+msgstr "链接创建于 {made}"
+
+msgid "Locations that require two-factor are left out of the feed. Google Calendar fetches the link from Google's servers, so it works there only when Kept can be reached from the internet."
+msgstr "要求双重验证的空间不会包含在订阅源中。Google 日历会从 Google 服务器抓取该链接,因此只有在 Kept 可从公网访问时才能正常使用。"
+
+msgid "Mail isn't configured on this server, so no email goes out yet."
+msgstr "此服务器未配置邮件服务,因此暂时不会发出邮件。"
+
+msgid "Mail isn't configured on this server."
+msgstr "此服务器尚未配置邮件服务。"
+
+msgid "Mark all read"
+msgstr "全部标为已读"
+
+msgid "Members joining and leaving"
+msgstr "成员加入与离开"
+
+msgid "Needs a connection: completing, snoozing, returning and marking read wait until you're back online."
+msgstr "需要联网:完成、延后、归还和标为已读等操作将在恢复网络后同步。"
+
+msgid "No check for due reminders has finished yet, so nobody gets reminders."
+msgstr "尚未完成过到期提醒检查,因此暂未向任何人发送提醒。"
+
+msgid "No longer due"
+msgstr "已不再到期"
+
+msgid "Not checked yet"
+msgstr "尚未检查"
+
+msgid "Not fetched yet"
+msgstr "尚未获取"
+
+msgid "Nothing is pushed or emailed in these hours; it waits until they end."
+msgstr "在此时间段内不会发送推送或邮件通知,消息将在免打扰结束后发出。"
+
+msgid "Nothing new"
+msgstr "暂无新版本"
+
+msgid "Notification settings"
+msgstr "通知设置"
+
+msgid "Notifications are blocked"
+msgstr "通知已被拦截"
+
+msgid "Notifications are blocked for Kept in this browser's settings. Allow them there, then come back."
+msgstr "此浏览器设置中已拦截 Kept 的通知。请先在浏览器中允许通知,然后再返回。"
+
+msgid "Notifications are on for this device"
+msgstr "此设备已开启通知"
+
+msgid "On iPhone and iPad, notifications work only from the installed app. Add Kept to your Home Screen, open it from there and turn them on. Until then, email reaches you."
+msgstr "在 iPhone 和 iPad 上,通知仅在从已安装的应用中打开时生效。请将 Kept 添加到主屏幕,从桌面图标打开后再开启通知。在此之前,通知会通过邮件发送给你。"
+
+msgid "Once a month: what AI did for you and what it used."
+msgstr "每月一次:汇总 AI 为你完成的工作与消耗用量。"
+
+msgid "Open {heading}"
+msgstr "打开 {heading}"
+
+msgid "Optional, to tell your webhooks apart."
+msgstr "选填,用于区分不同的 Webhook。"
+
+msgid "Overdue loans"
+msgstr "逾期借出"
+
+msgid "Push"
+msgstr "推送"
+
+msgid "Push is on"
+msgstr "推送已开启"
+
+msgid "Push isn't set up on this server. Email and the notification centre still work."
+msgstr "此服务器尚未配置推送通知,但电子邮件和通知中心仍可正常使用。"
+
+msgid "Push needs HTTPS. Over plain HTTP, email and the notification centre still work."
+msgstr "推送通知需要 HTTPS 连接。在明文 HTTP 下,邮件和通知中心仍可正常使用。"
+
+msgid "Push on since {added}"
+msgstr "推送已开启(自 {added} 起)"
+
+msgid "Push on since {added} · last delivered {last}"
+msgstr "推送开启于 {added} · 上次送达 {last}"
+
+msgid "Quiet hours"
+msgstr "免打扰时段"
+
+msgid "Quiet hours can't start and end at the same time."
+msgstr "免打扰时段的开始时间与结束时间不能相同。"
+
+msgid "Reminders have stopped going out"
+msgstr "提醒已停止发送"
+
+msgid "Reminders pop up here even when Kept is closed. Your browser asks first."
+msgstr "即使关闭 Kept,提醒也会在此弹出。浏览器会先向你请求权限。"
+
+msgid "Remove {name}"
+msgstr "移除 {name}"
+
+msgid "Remove the webhook {name}?"
+msgstr "移除 Webhook {name}?"
+
+msgid "Renew {heading}"
+msgstr "续期{heading}"
+
+msgid "Revoke the link made {made}"
+msgstr "撤销于 {made} 创建的链接"
+
+msgid "Revoke this calendar link?"
+msgstr "撤销此日历订阅链接?"
+
+msgid "Revoked"
+msgstr "已撤销"
+
+msgid "Role: {role}"
+msgstr "角色:{role}"
+
+msgid "Schedules due"
+msgstr "到期计划"
+
+msgid "Send a test email"
+msgstr "发送测试邮件"
+
+msgid "Send a test notification to {name}"
+msgstr "向 {name} 发送测试通知"
+
+msgid "Send a test notification to this device"
+msgstr "向此设备发送测试通知"
+
+msgid "Send a test to {name}"
+msgstr "向 {name} 发送测试"
+
+msgid "Snooze {heading}"
+msgstr "延后{heading}"
+
+msgid "Stop notifications on {name}?"
+msgstr "要停止在 {name} 上接收通知吗?"
+
+msgid "Test sent"
+msgstr "测试消息已发送"
+
+msgid "That device stops receiving push from Kept. Turn it on again from the device itself."
+msgstr "该设备将不再接收 Kept 的推送通知。如需恢复,请在该设备上重新开启。"
+
+msgid "The mail server didn't take it. Try again later."
+msgstr "邮件服务器未接收该请求,请稍后再试。"
+
+msgid "The test didn't arrive"
+msgstr "未收到测试通知"
+
+msgid "This browser can't receive notifications from Kept. Email still reaches you."
+msgstr "此浏览器无法接收 Kept 通知,但你仍会收到邮件通知。"
+
+msgid "Times are in <0>{zone}0>, your time zone."
+msgstr "时间均采用你的时区 <0>{zone}0>。"
+
+msgid "Turn off"
+msgstr "关闭"
+
+msgid "Turn off notifications on this device?"
+msgstr "关闭此设备上的通知?"
+
+msgid "Unread"
+msgstr "未读"
+
+msgid "Unread:"
+msgstr "未读:"
+
+msgid "Warranties running out"
+msgstr "即将过保的物品"
+
+msgid "Warranty · {on}"
+msgstr "保修 · {on}"
+
+msgid "Warranty registration · {on}"
+msgstr "保修注册 · {on}"
+
+msgid "Warranty registration deadlines"
+msgstr "保修注册截止日期"
+
+msgid "Was due {day}"
+msgstr "原定于 {day} 到期"
+
+msgid "Was due back {day}"
+msgstr "应于 {day} 归还"
+
+msgid "Was: {role}"
+msgstr "原角色:{role}"
+
+msgid "Webhook"
+msgstr "Webhook"
+
+msgid "Webhooks"
+msgstr "Webhooks"
+
+msgid "What's coming up arrives together, once a day."
+msgstr "即将到期的事项每天汇总推送一次。"
+
+msgid "Where Kept posts. Only its host is shown after this."
+msgstr "Kept 发送请求的接收地址。保存后仅显示主机名。"
+
+msgid "Your account has no email address, so Kept tells you here, in the app."
+msgstr "你的账号未绑定电子邮箱,因此 Kept 会直接在此应用内通知你。"
+
+msgid "Your account has no email address."
+msgstr "你的账号尚未设置邮箱地址。"
+
+msgid "Your claim pack is ready"
+msgstr "你的理赔资料包已就绪"
+
+msgid "Your insurance report is ready"
+msgstr "你的保险报告已就绪"
+
+msgid "Your monthly AI summary"
+msgstr "你的月度 AI 用量汇总"
+
+msgid "Your personal AI"
+msgstr "你的个人 AI"
+
+msgid "{0, plural, one {# claim} other {# claims}}"
+msgstr "{0, plural, one {# 条理赔} other {# 条理赔}}"
+
+msgid "{0, plural, one {# thing in {where}} other {# things in {where}}}"
+msgstr "{0, plural, one {{where} 中有 # 件物品} other {{where} 中有 # 件物品}}"
+
+msgid "{0, plural, one {Added # thing to {name}} other {Added # things to {name}}}"
+msgstr "{0, plural, one {已将 # 件物品添加到 {name}} other {已将 # 件物品添加到 {name}}}"
+
+msgid "{0, plural, one {Downloaded # time} other {Downloaded # times}}"
+msgstr "{0, plural, one {已下载 # 次} other {已下载 # 次}}"
+
+msgid "{0, plural, one {Ended # thing} other {Ended # things}}"
+msgstr "{0, plural, one {已结束 # 件物品} other {已结束 # 件物品}}"
+
+msgid "{0, plural, one {The thing still in use ends on the day of the incident. It leaves your counts and totals, and stays in the history.} other {The # things still in use end on the day of the incident. They leave your counts and totals, and stay in the history.}}"
+msgstr "{0, plural, one {仍在使用的物品将在事件当天终止使用。它将移出你的数量与总额统计,并保留在历史记录中。} other {仍在使用的 # 件物品将在事件当天终止使用。它们将移出你的数量与总额统计,并保留在历史记录中。}}"
+
+msgid "{0, plural, one {The thing you chose leaves your counts and totals, and stays in the history.} other {The # things you chose leave your counts and totals, and stay in the history.}}"
+msgstr "{0, plural, one {你选择的物品将不再计入数量和总额,并保留在历史记录中。} other {你选择的 # 件物品将不再计入数量和总额,并保留在历史记录中。}}"
+
+msgid "{d, plural, one {# day} other {# days}}"
+msgstr "{d, plural, one {# 天} other {# 天}}"
+
+msgid "{kind} on {day}"
+msgstr "{kind},{day}"
+
+msgid "{n, plural, one {Add # thing to an incident} other {Add # things to an incident}}"
+msgstr "{n, plural, one {将 # 件物品加入意外事件} other {将 # 件物品加入意外事件}}"
+
+msgid "{size}, kept until {keptUntil}."
+msgstr "{size},保留至 {keptUntil}。"
+
+msgid "1 {from} is worth"
+msgstr "1 {from} 兑换"
+
+msgid "A claim pack carries prices and documents, so only owners and admins make it."
+msgstr "理赔材料包包含价格与文档,因此仅所有者和管理员可生成。"
+
+msgid "A new incident"
+msgstr "新建事故记录"
+
+msgid "A new link stops the old one working."
+msgstr "生成新链接后,旧链接将失效。"
+
+msgid "A number above 0, with at most 8 decimals, like 48.65."
+msgstr "大于 0 的数字,最多 8 位小数,例如 48.65。"
+
+msgid "A PDF for your insurer: each thing with its photo, brand, model, serial, purchase date and price, current value and receipts, with totals per room and per currency."
+msgstr "面向保险公司的 PDF 报告:列出每件物品的照片、品牌、型号、序列号、购买日期与价格、当前估值及收据,并按房间和币种汇总。"
+
+msgid "A rate is missing, so there's no converted total"
+msgstr "缺少汇率,无法显示折算总计"
+
+msgid "A thing"
+msgstr "物品"
+
+msgid "A ZIP for your insurer: the insurance report, every receipt and invoice as you uploaded it, the photos, and a list of serial numbers. You share it with a link that expires."
+msgstr "面向保险公司的 ZIP 压缩包:包含保险理赔报告、你上传的所有收据和发票原件、照片以及序列号清单。可通过带有效期的链接分享。"
+
+msgid "Add a document"
+msgstr "添加文档"
+
+msgid "Add a rate"
+msgstr "添加汇率"
+
+msgid "Add exchange rates"
+msgstr "添加汇率"
+
+msgid "Add one when you want totals in several currencies turned into one, like USD to EGP."
+msgstr "当你需要将多种货币的总额换算为单一货币(例如美元换算为埃及镑)时,可在此添加汇率。"
+
+msgid "Add them to"
+msgstr "将它们添加到"
+
+msgid "Add to incident"
+msgstr "添加到事故记录"
+
+msgid "Also total in (optional)"
+msgstr "同时折算汇总为(可选)"
+
+msgid "An owner or admin records a burglary, fire, flood or loss here."
+msgstr "所有者或管理员可在此记录入室盗窃、火灾、水灾或财产损失事件。"
+
+msgid "Anyone with the link can download what you paid, your receipts and the serial numbers, without signing in, until it expires or you revoke it. Passwords and codes are never in it."
+msgstr "任何拥有此链接的人无需登录即可下载你的购买价格、收据和序列号,直到链接过期或被你撤销。密码和验证码绝不会包含在其中。"
+
+msgid "Applies from"
+msgstr "生效日期"
+
+msgid "As of"
+msgstr "截至日期"
+
+msgid "Back to this location's incidents"
+msgstr "返回此空间的事故记录"
+
+msgid "Burglary"
+msgstr "入室盗窃"
+
+msgid "Change the rate"
+msgstr "更改汇率"
+
+msgid "Change the rate from {day}"
+msgstr "修改自 {day} 起的汇率"
+
+msgid "Choose a location."
+msgstr "选择一个空间。"
+
+msgid "Choose the currency you convert from."
+msgstr "选择要换算的源币种。"
+
+msgid "Choose the currency you convert to."
+msgstr "选择要换算成的目标币种。"
+
+msgid "Choose two different currencies."
+msgstr "请选择两种不同的币种。"
+
+msgid "Choose what goes in it"
+msgstr "选择要放入其中的物品"
+
+msgid "Claims under {name}"
+msgstr "{name} 下的理赔"
+
+msgid "Copy it now: Kept shows it only this once."
+msgstr "请立即复制:Kept 仅显示这一次。"
+
+msgid "Couldn't check on the claim pack"
+msgstr "无法查询理赔资料包状态"
+
+msgid "Couldn't make the claim pack"
+msgstr "无法生成理赔资料包"
+
+msgid "Create link"
+msgstr "创建链接"
+
+msgid "Delete the {pair} rate from {day}?"
+msgstr "要删除 {day} 的 {pair} 汇率吗?"
+
+msgid "Delete the rate from {day}"
+msgstr "删除 {day} 的汇率"
+
+msgid "Documents for {name}"
+msgstr "{name} 的文档"
+
+msgid "Edit the incident"
+msgstr "编辑事故记录"
+
+msgid "Fire"
+msgstr "火灾"
+
+msgid "Flood"
+msgstr "水灾"
+
+msgid "For <0>{0}0>"
+msgstr "用于 <0>{0}0>"
+
+msgid "For <0>{incidentName}0>"
+msgstr "针对 <0>{incidentName}0>"
+
+msgid "For <0>{what}0>"
+msgstr "用于 <0>{what}0>"
+
+msgid "For the insurer"
+msgstr "提供给保险公司"
+
+msgid "From {0} to {1}. To change the pair or the day, add a new rate."
+msgstr "从 {0} 到 {1}。如需更改币种或日期,请添加新汇率。"
+
+msgid "From {day} · by <0>{who}0>"
+msgstr "自 {day} · 由 <0>{who}0> 操作"
+
+msgid "Gathering the files…"
+msgstr "正在打包文件…"
+
+msgid "Get the ZIP"
+msgstr "下载 ZIP"
+
+msgid "How much one unit is worth in the other."
+msgstr "1 单位外币可兑换多少本币。"
+
+msgid "I understand the link shares prices and documents"
+msgstr "我理解此链接会公开分享价格和文档"
+
+msgid "If something is stolen, burnt, flooded or lost, record it here, or select the things in a location's list and choose Add to incident."
+msgstr "如果发生被盗、火灾、水浸或遗失,可在此记录,或在空间的物品列表中选中物品后选择“添加到事故记录”。"
+
+msgid "Include photos"
+msgstr "包含照片"
+
+msgid "Insurer: <0>{0}0>"
+msgstr "保险公司:<0>{0}0>"
+
+msgid "Insurer's reference"
+msgstr "保险公司参考号"
+
+msgid "Insurer's reference (optional)"
+msgstr "保险公司参考号(可选)"
+
+msgid "It can't be in the future."
+msgstr "不能是未来的日期。"
+
+msgid "It stops working at once, for everyone who has it. You can make a new one."
+msgstr "撤销后将立即对所有持有者失效,你可以重新生成一个新的。"
+
+msgid "It's kept for 7 days. Make a new one from the incident or the selection."
+msgstr "资料包将保留 7 天。之后可从事故记录或选中物品中重新生成。"
+
+msgid "Keep the notes under {NOTES_MAX} characters."
+msgstr "备注请保持在 {NOTES_MAX} 个字符以内。"
+
+msgid "Kept converts only with a rate you entered, never an estimate. Add one dated on or before the report's day, or make the report without a converted total."
+msgstr "Kept 仅使用你录入的汇率进行换算,绝不使用估算值。请添加报告日期当天或之前的汇率,或在生成报告时不启用折算总计。"
+
+msgid "Kept converts totals only with a rate you entered here, for that pair or its inverse. It never estimates one, and never goes through a third currency: without a rate, totals stay per currency."
+msgstr "Kept 仅使用你在此处录入的对应汇率或其倒数进行金额换算,绝不自行估算,也不会通过第三方货币中转:若无汇率,总计将按各币种分别显示。"
+
+msgid "Kept until {keptUntil}."
+msgstr "保留至 {keptUntil}。"
+
+msgid "Kind or reference"
+msgstr "类型或参考号"
+
+msgid "last {lastDownload}"
+msgstr "上次:{lastDownload}"
+
+msgid "Link expires {linkExpires}"
+msgstr "链接有效期至 {linkExpires}"
+
+msgid "Link lasts"
+msgstr "链接有效期"
+
+msgid "Link revoked"
+msgstr "链接已撤销"
+
+msgctxt "incident kind"
+msgid "Loss"
+msgstr "损失"
+
+msgid "Make a claim pack from an incident's page, or select things in a location's list and choose Claim pack."
+msgstr "可在理赔/意外事件页面生成理赔资料包,或在空间列表中勾选物品后选择「理赔资料包」。"
+
+msgid "Make another"
+msgstr "再创建一个"
+
+msgid "Make the claim pack"
+msgstr "生成理赔资料包"
+
+msgid "Making the claim pack"
+msgstr "正在生成理赔材料包"
+
+msgid "Mark these destroyed"
+msgstr "将选中项标记为损毁"
+
+msgid "Mark these lost"
+msgstr "将以下物品标为遗失"
+
+msgid "Mark these stolen"
+msgstr "将以下物品标为被盗"
+
+msgid "Missing rates"
+msgstr "缺少汇率"
+
+msgid "Needs a connection: recording an incident waits until you're back online."
+msgstr "需要网络连接:记录事故需等待恢复在线后才能提交。"
+
+msgid "New incident"
+msgstr "新建事件"
+
+msgid "New link"
+msgstr "新建链接"
+
+msgid "No exchange rates yet"
+msgstr "暂无汇率"
+
+msgid "No incidents"
+msgstr "暂无事故记录"
+
+msgid "No link yet. Nobody can download it until you make one."
+msgstr "暂无链接。生成链接后他人才可下载。"
+
+msgid "No location to report on"
+msgstr "没有可生成报告的空间"
+
+msgid "No report for this incident"
+msgstr "此事件暂无报告"
+
+msgid "Not downloaded yet"
+msgstr "尚未下载"
+
+msgid "Notes (optional)"
+msgstr "备注(可选)"
+
+msgid "Nothing yet. In the location's list, choose Select, pick the things, then Add to incident."
+msgstr "暂无物品。请在空间列表中点击「选择」,勾选物品后点击「添加到事故记录」。"
+
+msgid "Only an owner or admin makes one"
+msgstr "仅所有者或管理员可创建"
+
+msgid "Only an owner or admin of this account changes its rates."
+msgstr "只有此账号的拥有者或管理员才能更改汇率。"
+
+msgid "Pick the day it applies from."
+msgstr "选择生效日期。"
+
+msgid "Pick the day it happened."
+msgstr "选择发生日期。"
+
+msgid "Police reference"
+msgstr "报警回执编号"
+
+msgid "Police reference (optional)"
+msgstr "报警回执号(可选)"
+
+msgid "Police: <0>{0}0>"
+msgstr "警方报案回执:<0>{0}0>"
+
+msgid "Rate"
+msgstr "汇率"
+
+msgid "Rate added"
+msgstr "已添加汇率"
+
+msgid "Rate changed"
+msgstr "汇率已更改"
+
+msgid "Rate deleted"
+msgstr "汇率已删除"
+
+msgid "Record"
+msgstr "记录"
+
+msgid "Recorded {name}"
+msgstr "已记录 {name}"
+
+msgid "Revoke the link?"
+msgstr "要撤销此链接吗?"
+
+msgid "Search incidents"
+msgstr "搜索理赔/意外事件"
+
+msgid "Share the ZIP"
+msgstr "分享 ZIP"
+
+msgid "Take {0} out of the incident"
+msgstr "将 {0} 移出此事故"
+
+msgid "Take out"
+msgstr "取出"
+
+msgid "The insurance report needs Money on in a location, and a role that sees prices there."
+msgstr "生成保险报告需要在空间中开启财务功能,且当前角色有权查看价格。"
+
+msgid "The insurance report needs Money on in its location, and a role that sees prices."
+msgstr "保险报告需要在所在空间中开启“金额”功能,且当前角色有权查看价格。"
+
+msgid "The things stay as they are; only the incident and its references go. You can undo this for 7 days from the history."
+msgstr "物品本身保持不变,仅删除该事件及其关联记录。7 天内可从历史记录中撤销。"
+
+msgid "This browser can't save files here. Open Kept in Safari to download it."
+msgstr "当前浏览器无法在此保存文件。请在 Safari 中打开 Kept 以下载。"
+
+msgid "This claim pack has expired"
+msgstr "此理赔资料包已过期"
+
+msgid "This includes prices and documents"
+msgstr "包含价格和文档"
+
+msgid "Took {what} out of {name}"
+msgstr "已从 {name} 取出 {what}"
+
+msgid "Totals from that day use the rate before it, or show per currency."
+msgstr "该日起的总计将使用此前的汇率,或按币种分别显示。"
+
+msgid "Totals stay per currency; this adds one converted with your exchange rates."
+msgstr "分币种总计会保留;启用后还会额外显示按你的汇率换算后的总计。"
+
+msgid "Until a newer rate for the same pair."
+msgstr "直到出现同一币种对的更新汇率为止。"
+
+msgid "Values are the latest on or before this day."
+msgstr "所选数值为该日及之前的最新估值。"
+
+msgid "What happened"
+msgstr "经过描述"
+
+msgid "What it affected"
+msgstr "受影响的内容"
+
+msgid "Your link"
+msgstr "你的链接"
+
+msgid "{0, plural, one {# location} other {# locations}}"
+msgstr "{0, plural, one {# 个空间} other {# 个空间}}"
+
+msgid "Find an account by its owner"
+msgstr "按所有者查找账号"
+
+msgid "Limit an account"
+msgstr "限制账号"
+
+msgid "Consumables"
+msgstr "耗材"
+
+msgid "Export"
+msgstr "导出"
+
+msgid "Logo of {name}"
+msgstr "{name} 的徽标"
+
+msgid "Remove the logo?"
+msgstr "移除徽标?"
+
+msgid "The brand's icon shows instead."
+msgstr "将改用品牌图标显示。"
+
+msgid "Replace the logo"
+msgstr "更换徽标"
+
+msgid "Add a logo"
+msgstr "添加徽标"
+
+msgid "Remove the logo"
+msgstr "移除徽标"
+
+msgid "PNG, JPEG, WebP or SVG, up to 2 MB."
+msgstr "支持 PNG、JPEG、WebP 或 SVG,最大 2 MB。"
+
+msgid "Connections"
+msgstr "外部连接"
+
+msgid "Ask about your things"
+msgstr "询问关于你物品的问题"
+
+msgid "Ask where something is or what's due, or ask for a change you confirm before it's made. Your conversations are private to you."
+msgstr "询问物品位置或近期到期事项,或请求执行操作(变更前会由你确认)。你的对话仅自己可见。"
+
+msgid "Connect other apps"
+msgstr "连接其他应用"
+
+msgid "Connect an app"
+msgstr "连接应用"
+
+msgid "Warranty changed"
+msgstr "保修已更改"
+
+msgid "Claim changed"
+msgstr "已更新理赔"
+
+msgid "Claim deleted"
+msgstr "理赔记录已删除"
+
+msgid "Valuation changed"
+msgstr "估值已更改"
+
+msgid "Valuation deleted"
+msgstr "已删除估值"
+
+msgid "Loan added"
+msgstr "已添加借出记录"
+
+msgid "Loan changed"
+msgstr "借出记录已更改"
+
+msgid "Loan returned"
+msgstr "借出物品已归还"
+
+msgid "Loan deleted"
+msgstr "借出记录已删除"
+
+msgid "Schedule added"
+msgstr "已添加计划"
+
+msgid "Schedule changed"
+msgstr "计划已更改"
+
+msgid "Schedule deleted"
+msgstr "已删除计划"
+
+msgid "Schedule snoozed"
+msgstr "已延后计划"
+
+msgid "Snooze cleared"
+msgstr "已清除延后提醒"
+
+msgid "Next one skipped"
+msgstr "已跳过下一次"
+
+msgid "Service changed"
+msgstr "保养计划已更改"
+
+msgid "Service deleted"
+msgstr "维护记录已删除"
+
+msgid "Document added"
+msgstr "已添加文档"
+
+msgid "Document changed"
+msgstr "文档已更改"
+
+msgid "Document renewed"
+msgstr "文档已续期"
+
+msgid "Document deleted"
+msgstr "已删除文档"
+
+msgid "Incident recorded"
+msgstr "已记录事故"
+
+msgid "Incident changed"
+msgstr "事故记录已更改"
+
+msgid "Incident's things changed"
+msgstr "事故涉及物品已更改"
+
+msgid "Incident deleted"
+msgstr "事故记录已删除"
+
+msgid "Exchange rate set"
+msgstr "已设置汇率"
+
+msgid "Exchange rate deleted"
+msgstr "汇率已删除"
+
+msgid "Brand logo changed"
+msgstr "品牌徽标已更改"
+
+msgid "Brand logo removed"
+msgstr "已移除品牌徽标"
+
+msgid "Ends on"
+msgstr "结束于"
+
+msgid "Term (months)"
+msgstr "期限(月)"
+
+msgid "Opened on"
+msgstr "提交日期"
+
+msgid "Covered"
+msgstr "在保修范围内"
+
+msgid "Days of notice"
+msgstr "提前通知天数"
+
+msgid "Notice on the meter"
+msgstr "表计提示"
+
+msgid "Every (months)"
+msgstr "每隔(月)"
+
+msgid "Every (on the meter)"
+msgstr "每隔(按表计读数)"
+
+msgid "Counted from"
+msgstr "起算自"
+
+msgid "Counted from the reading"
+msgstr "根据读数计算"
+
+msgid "Snoozed until"
+msgstr "已延后至"
+
+msgid "Snoozed until the reading"
+msgstr "已延后至下次抄表"
+
+msgid "Skip the next one"
+msgstr "跳过下一次"
+
+msgid "Active"
+msgstr "有效"
+
+msgid "Title"
+msgstr "标题"
+
+msgid "Happened on"
+msgstr "发生日期"
+
+msgid "Insurer reference"
+msgstr "保险公司参考号"
+
+msgid "Past {at}"
+msgstr "已过 {at}"
+
+msgid "Kept exports at most five lists an hour. Try again later."
+msgstr "Kept 每小时最多导出五份列表。请稍后再试。"
+
+msgid "Export or print this list"
+msgstr "导出或打印此清单"
+
+msgid "Export view (CSV)"
+msgstr "导出当前视图 (CSV)"
+
+msgid "The things in this list, as a spreadsheet"
+msgstr "此列表中的物品(导出为电子表格)"
+
+msgid "A PDF of this list, up to {0} things"
+msgstr "此列表的 PDF 文件,最多包含 {0} 件物品"
+
+msgid "Print this list"
+msgstr "打印此列表"
+
+msgid "Reading the list…"
+msgstr "正在读取列表…"
+
+msgid "Narrow the list to {0} things to print it."
+msgstr "请将列表缩小至 {0} 件物品以内再打印。"
+
+msgid "There's nothing in this list to print."
+msgstr "此列表中没有可打印的内容。"
+
+msgid "CSV"
+msgstr "CSV"
+
+msgid "Homebox export"
+msgstr "Homebox 导出文件"
+
+msgid "Homebox"
+msgstr "Homebox"
+
+msgid "Kept export"
+msgstr "Kept 导出包"
+
+msgid "LubeLogger CSV"
+msgstr "LubeLogger CSV"
+
+msgid "Imported by"
+msgstr "导入者"
+
+msgid "Why it needs a look"
+msgstr "需要查看的原因"
+
+msgid "Claim · open"
+msgstr "理赔 · 进行中"
+
+msgid "Claim · closed"
+msgstr "理赔 · 已关闭"
+
+msgid "{provider} warranty"
+msgstr "{provider} 保修"
+
+msgid "Bought {first}, covered from {from} to {until}; today is {pct} of the way"
+msgstr "购买于 {first},覆盖期自 {from} 至 {until};目前已过 {pct}"
+
+msgid "Meters not read lately"
+msgstr "近期未抄表的表计"
+
+msgid "Readings due"
+msgstr "待抄表读数"
+
+msgid "Reading needed"
+msgstr "需要读数"
+
+msgid "Reading due {day}"
+msgstr "应于 {day} 抄表"
+
+msgid "Reading needed · {on}"
+msgstr "需要抄表 · {on}"
+
+msgid "{0, plural, one {# earlier term} other {# earlier terms}}"
+msgstr "{0, plural, one {# 个早期期限} other {# 个早期期限}}"
+
+msgid "{0, plural, one {a month, over the last month} other {a month, over the last # months}}"
+msgstr "{0, plural, one {每月,近 1 个月} other {每月,近 # 个月}}"
+
+msgid "{0, plural, one {the last full fill} other {the last # full fills}}"
+msgstr "{0, plural, one {上次加满} other {最近 # 次加满}}"
+
+msgid "{amount} per {u}"
+msgstr "{amount} / {u}"
+
+msgid "{amount}/{unit}"
+msgstr "{amount}/{unit}"
+
+msgid "{days, plural, one {Due in # day} other {Due in # days}}"
+msgstr "{days, plural, one {还有 # 天到期} other {还有 # 天到期}}"
+
+msgid "{lead, plural, one {Reminds # day before} other {Reminds # days before}}"
+msgstr "{lead, plural, one {提前 # 天提醒} other {提前 # 天提醒}}"
+
+msgid "{price} per {unit}"
+msgstr "{price} / {unit}"
+
+msgid "{v} {u} an hour"
+msgstr "每小时 {v} {u}"
+
+msgid "{v} kWh/100 km"
+msgstr "{v} kWh/100 km"
+
+msgid "{v} L/100 km"
+msgstr "{v} 升/百公里"
+
+msgid "{v} mi/kWh"
+msgstr "{v} 英里/千瓦时"
+
+msgid "{v} mpg"
+msgstr "{v} mpg"
+
+msgid "≈ {amount}"
+msgstr "约 {amount}"
+
+msgid "A missed fill-up breaks the count. Consumption shows again after two full fills with odometer readings."
+msgstr "漏记一次加油会中断统计。在连续记录两次带里程表读数的加满后,油耗会重新显示。"
+
+msgid "A new station: it's added to your vendors when you save."
+msgstr "新站点:保存后将添加到你的商家列表中。"
+
+msgid "A PDF of <0>{0}0>'s history: the odometer readings with their photos, every service with its lines and invoices, the fuel summary and the documents."
+msgstr "<0>{0}0> 的历史档案 PDF:包含里程表读数及照片、所有保养记录及明细发票、油耗汇总以及相关文档。"
+
+msgid "All of it"
+msgstr "全部"
+
+msgid "Amount"
+msgstr "金额"
+
+msgid "Amount, {0}"
+msgstr "金额({0})"
+
+msgid "by month"
+msgstr "按月"
+
+msgid "by unit"
+msgstr "按单位"
+
+msgid "Charge"
+msgstr "充电"
+
+msgid "Consumption"
+msgstr "能耗 / 油耗"
+
+msgid "Consumption is measured from one full fill to the next; this one counts in the next full's."
+msgstr "油耗按两次加满油之间的区间计算;本次加油将计入下一次加满的统计中。"
+
+msgid "Consumption needs the odometer on the fills. Add it when you log fuel."
+msgstr "计算能耗需要在每次加油/充电记录中填写里程表读数。请在记录时补全。"
+
+msgid "Consumption needs two full fills in the same unit, with no fill in another unit between them."
+msgstr "计算能耗需要同一单位下的两次加满/充满记录,且两者之间不能夹杂其他单位的记录。"
+
+msgid "Consumption needs two full fills with odometer readings."
+msgstr "计算油耗需要两次带里程表读数的加满记录。"
+
+msgid "Consumption skips the gap, so it stays right."
+msgstr "消耗量统计会自动跳过该间隔,以保持数据准确。"
+
+msgid "Consumption, {0}"
+msgstr "能耗,{0}"
+
+msgid "Cost (optional)"
+msgstr "费用(可选)"
+
+msgid "Cost:"
+msgstr "费用:"
+
+msgid "Costs"
+msgstr "费用"
+
+msgid "Costs appear only for readers who can see money."
+msgstr "费用仅对拥有金额查看权限的读者显示。"
+
+msgid "Costs appear only if you can see money. You can't in this location, so this one has none."
+msgstr "仅当你有查看金额的权限时才会显示费用。你在此空间没有该权限,因此此处无费用信息。"
+
+msgid "Costs:"
+msgstr "费用:"
+
+msgid "Couldn't log the fuel"
+msgstr "无法记录加油信息"
+
+msgid "Documents of {name}"
+msgstr "{name} 的文档"
+
+msgid "Enter a number, like 52340."
+msgstr "请输入数字,例如 52340。"
+
+msgid "Enter how much, like 40 or 38.5."
+msgstr "输入数值,例如 40 或 38.5。"
+
+msgid "Expired"
+msgstr "已过期"
+
+msgid "expires {day}"
+msgstr "有效期至 {day}"
+
+msgid "Fill"
+msgstr "加满"
+
+msgid "Fills and charges"
+msgstr "加油与充电"
+
+msgid "Find a station"
+msgstr "查找加油站"
+
+msgid "From and to"
+msgstr "起始与目标"
+
+msgid "Fuel & charging"
+msgstr "加油与充电"
+
+msgid "Fuel logged"
+msgstr "已记录加油"
+
+msgid "fuel only"
+msgstr "仅加油记录"
+
+msgid "Full"
+msgstr "完整"
+
+msgid "Full fill"
+msgstr "加满"
+
+msgid "Full tank"
+msgstr "加满油"
+
+msgid "gal"
+msgstr "加仑"
+
+msgid "History report"
+msgstr "历史记录报告"
+
+msgid "I missed a fill-up before this one"
+msgstr "我在这次之前漏记了一次加满"
+
+msgid "Include"
+msgstr "包含"
+
+msgid "Issued {issued}"
+msgstr "签发于 {issued}"
+
+msgid "Issued on (optional)"
+msgstr "签发日期(可选)"
+
+msgid "Issued on or before the day it runs out."
+msgstr "签发日期应早于或等于到期日。"
+
+msgid "Its odometer reading goes with it. You can undo this."
+msgstr "关联的里程表读数也会一并移除。此操作可撤销。"
+
+msgid "kWh"
+msgstr "千瓦时 (kWh)"
+
+msgid "L"
+msgstr "升"
+
+msgid "Latest:"
+msgstr "最新:"
+
+msgid "Litres"
+msgstr "升"
+
+msgid "Loading the documents"
+msgstr "正在加载文档"
+
+msgid "Log fuel"
+msgstr "记录加油"
+
+msgid "Log fuel after a fill-up or a charge to see consumption and the cost per km."
+msgstr "每次加油或充电后记录一次,即可查看能耗与每公里成本。"
+
+msgid "Missed a fill-up before this one"
+msgstr "此记录前漏记了一次加油/充电"
+
+msgid "Month"
+msgstr "月"
+
+msgid "Needs a connection: it has money."
+msgstr "需要联网:其中包含金额数据。"
+
+msgid "No fills yet"
+msgstr "暂无加油记录"
+
+msgid "No fills yet. Log one to start the consumption and the cost per km."
+msgstr "暂无加油记录。记录一次即可开始统计油耗与每公里成本。"
+
+msgid "No match: this name is added as a new station"
+msgstr "无匹配站点:该名称将作为新站点添加"
+
+msgid "Odometer, {0}"
+msgstr "里程表,{0}"
+
+msgid "Partial"
+msgstr "部分"
+
+msgid "Photo of the odometer"
+msgstr "里程表照片"
+
+msgid "Pick the day."
+msgstr "选择日期。"
+
+msgid "Price per {u}, {0}"
+msgstr "每 {u} 单价,{0}"
+
+msgid "Proof photos"
+msgstr "凭证照片"
+
+msgid "Pump receipt"
+msgstr "加油/充电小票"
+
+msgid "Read in LABEL mode: VIN, plate and licence expiry"
+msgstr "在标签模式下识别:车架号 (VIN)、车牌号与证件有效期"
+
+msgid "Read the card"
+msgstr "读取名片/卡片"
+
+msgid "Remove the fill of {what} on {day}?"
+msgstr "移除 {day} 的 {what} 加注记录?"
+
+msgid "Removed the fill of {what}"
+msgstr "已移除 {what} 的加油记录"
+
+msgid "Replace the receipt"
+msgstr "替换收据"
+
+msgid "Search stations"
+msgstr "搜索加油站/充电站"
+
+msgid "Show as table"
+msgstr "以表格显示"
+
+msgid "Station"
+msgstr "站点"
+
+msgid "The odometer reading looks off, so it waits in your Inbox for a look."
+msgstr "里程表读数似乎有异常,已暂存于收件箱待你核实。"
+
+msgid "The odometer reading waits for review"
+msgstr "里程表读数等待审核"
+
+msgid "The start has to be on or before the end."
+msgstr "开始日期必须早于或等于结束日期。"
+
+msgid "To full"
+msgstr "加满至"
+
+msgid "US gallons"
+msgstr "美制加仑"
+
+msgid "Use the arrow keys to move between points."
+msgstr "使用方向键在各数据点之间移动。"
+
+msgid "Valid"
+msgstr "有效"
+
+msgid "vehicle document"
+msgstr "车辆文档"
+
+msgid "{0, plural, one {# day} other {# days}}"
+msgstr "{0, plural, one {# 天} other {# 天}}"
+
+msgid "{count, plural, one {# line} other {# lines}}"
+msgstr "{count, plural, one {# 行} other {# 行}}"
+
+msgid "{typed} {unit} is lower than {before} {unit} on {on}. Readings can't go down: check the digits, or record that the meter was replaced."
+msgstr "{typed} {unit} 低于 {on} 的 {before} {unit}。表计读数不能倒退:请核对数字,或记录表计已更换。"
+
+msgid "A new meter starts again from 0. Kept adds what the old one had reached, so the history keeps going up."
+msgstr "更换新表计后会从 0 重新计数。Kept 会累加旧表计的最终读数,使历史累计读数保持连续递增。"
+
+msgid "Add the first reading"
+msgstr "添加第一条读数"
+
+msgid "AI is paused here, so the invoice waits to be read. Type the lines, or come back later."
+msgstr "此处已暂停 AI,因此发票暂时等待识别。你可以手动填写明细,或稍后再来。"
+
+msgid "Canadian dollars (CAD)"
+msgstr "加拿大元 (CAD)"
+
+msgid "Confirm all"
+msgstr "全部确认"
+
+msgid "Couldn't discard the draft"
+msgstr "无法丢弃草稿"
+
+msgid "Couldn't read the invoice"
+msgstr "无法读取该发票"
+
+msgid "Couldn't upload the photo"
+msgstr "无法上传照片"
+
+msgid "Discard draft"
+msgstr "放弃草稿"
+
+msgid "Discard this draft?"
+msgstr "丢弃此草稿?"
+
+msgid "Draft discarded"
+msgstr "已丢弃草稿"
+
+msgid "Drafts only"
+msgstr "仅草稿"
+
+msgid "Due {0}"
+msgstr "到期时间:{0}"
+
+msgid "Due at {0} {1}"
+msgstr "到期时间:{0} {1}"
+
+msgid "Enter the number on the meter, like 53000, or leave it empty."
+msgstr "请输入表计上显示的数字(如 53000),或留空。"
+
+msgid "Enter the reading it carries on from, like 51220."
+msgstr "输入接续起始读数,例如 51220。"
+
+msgid "Enter the reading, like 53000 or 53000.5."
+msgstr "输入读数,例如 53000 或 53000.5。"
+
+msgid "Finding things with a meter"
+msgstr "查找带有表计的物品"
+
+msgid "Finish logging"
+msgstr "完成记录"
+
+msgid "Fits: {delta} {unit} since {before} {unit} on {on}, about {perDay} {unit} a day."
+msgstr "正常:自 {on} 的 {before} {unit} 以来增加 {delta} {unit},日均约 {perDay} {unit}。"
+
+msgid "Fits: {delta} {unit} since {before} {unit} on {on}."
+msgstr "正常:自 {on} 的 {before} {unit} 以来增加 {delta} {unit}。"
+
+msgid "Invoice page {0}"
+msgstr "发票第 {0} 页"
+
+msgid "It's right"
+msgstr "确认无误"
+
+msgid "Its invoice and what was read from it go too. This can't be undone."
+msgstr "其发票和从中识别的内容也会一并删除。此操作无法撤销。"
+
+msgid "Kept as a draft on its Services tab until you save it."
+msgstr "在保存前将作为草稿保留在“保养”标签页中。"
+
+msgid "Kept as proof"
+msgstr "作为凭证保留"
+
+msgid "Kept checks it against your other readings when it syncs; if it doesn't fit, it waits in your Inbox."
+msgstr "Kept 会在同步时将其与其他读数进行比对;如果数据存在异常,会留在收件箱中等待确认。"
+
+msgid "Kept couldn't read the invoice. Type the lines."
+msgstr "Kept 无法识别该发票,请手动输入明细行。"
+
+msgid "Kept tracks <0>{0}0> from this reading on: its estimates and the services due by distance start here. You can add it later from its page."
+msgstr "Kept 将从此读数开始追踪 <0>{0}0>:估算值和按里程计算的保养计划都将从这里起算。你稍后也可以在其页面补充。"
+
+msgid "Label photos go on <0>{0}0>"
+msgstr "标签照片将保存在 <0>{0}0>"
+
+msgid "Last read <0>{0} {1}0>, {2}"
+msgstr "上次读数:<0>{0} {1}0>,{2}"
+
+msgid "Last reading <0>{0} {unit}0>, {1}"
+msgstr "上次读数 <0>{0} {unit}0>,{1}"
+
+msgid "Line kind"
+msgstr "明细类型"
+
+msgid "Log a service with its invoice, and it shows here with what it cost."
+msgstr "登记一次维护保养并附上发票,即可在此看到相应记录与费用。"
+
+msgid "Matches “{match}”"
+msgstr "匹配“{match}”"
+
+msgid "Meter removed"
+msgstr "已移除表计"
+
+msgid "No connection. The reading is saved on this phone and checked against the others when it syncs."
+msgstr "当前无网络连接。读数已保存在此手机上,同步后将与其他读数进行校验。"
+
+msgid "no matching line"
+msgstr "无匹配行"
+
+msgid "No services yet"
+msgstr "暂无保养记录"
+
+msgid "Nothing on this phone has a meter yet"
+msgstr "此手机上还没有带表计的物品"
+
+msgid "Open Kept once while online, so this phone has your things and their meters."
+msgstr "请在联网状态下至少打开一次 Kept,以便此手机缓存你的物品和表计信息。"
+
+msgid "Optional. It joins the meter's proof photos."
+msgstr "可选。它会一并加入该表计的佐证照片。"
+
+msgid "Photo added. It joins the odometer proof strip."
+msgstr "照片已添加,已加入里程表凭证序列。"
+
+msgid "Pick the day it was read."
+msgstr "选择抄表日期。"
+
+msgid "Read by AI: {0}, and they don't add up to the total"
+msgstr "AI 识别结果:{0},且各项之和与总计不符"
+
+msgid "Read by AI: {0}, total matches"
+msgstr "AI 识别:{0},与总计相符"
+
+msgid "Read by AI: check it"
+msgstr "由 AI 识别:请核对"
+
+msgid "Read by AI: no lines found. Type them."
+msgstr "AI 未识别出明细行,请手动输入。"
+
+msgid "Reading ({unit}), optional"
+msgstr "读数({unit}),可选"
+
+msgid "Reading the invoice…"
+msgstr "正在识别发票…"
+
+msgid "Reading, optional"
+msgstr "读数(可选)"
+
+msgid "Record and save the reading"
+msgstr "记录并保存读数"
+
+msgid "restarts at {0} {1}"
+msgstr "于 {0} {1} 重置"
+
+msgid "Save reading"
+msgstr "保存读数"
+
+msgid "Saved on this phone"
+msgstr "已保存在此手机上"
+
+msgid "Saved only"
+msgstr "仅已保存"
+
+msgid "Search lines, vendor, notes"
+msgstr "搜索明细、商家、备注"
+
+msgid "Search services"
+msgstr "搜索维护记录"
+
+msgid "Service draft started from an invoice"
+msgstr "已根据发票创建保养草稿"
+
+msgid "Services"
+msgstr "服务"
+
+msgid "Services have money in them. A reading alone can be logged offline."
+msgstr "保养服务记录包含金额,需要联网;仅记录表计读数可离线保存。"
+
+msgid "Suggested line items from the invoice"
+msgstr "从发票中识别出的建议明细"
+
+msgid "Taken on"
+msgstr "记录日期"
+
+msgid "That's {delta} {unit} in {days}, about {perDay} {unit} a day, over the limit of {limit} {unit} a day. Is it right?"
+msgstr "相当于 {days} 天内增加 {delta} {unit},约每日 {perDay} {unit},超过了每日 {limit} {unit} 的上限。确认无误吗?"
+
+msgid "The invoice shows $. Is it US dollars or Canadian dollars?"
+msgstr "发票上显示符号为 $。请问这是美元 (USD) 还是加拿大元 (CAD)?"
+
+msgid "The old meter had reached ({unit})"
+msgstr "旧表计已达到的读数({unit})"
+
+msgid "This phone isn't ready to save offline yet. Try again in a moment."
+msgstr "此手机暂未准备好离线保存功能,请稍后再试。"
+
+msgid "US dollars (USD)"
+msgstr "美元 (USD)"
+
+msgid "waiting to sync"
+msgstr "等待同步"
+
+msgid "Waiting to sync"
+msgstr "等待同步"
+
+msgid "was estimated ~{0}"
+msgstr "估算为约 {0}"
+
+msgid "What did you read?"
+msgstr "识别到了什么?"
+
+msgid "Make {0} secret?"
+msgstr "将 {0} 设为私密?"
+
+msgid "Make {0} plain?"
+msgstr "确定将 {0} 设为普通字段吗?"
+
+msgid "Change the kind of {0}"
+msgstr "更改 {0} 的类型"
+
+msgid "{0} is secret now"
+msgstr "{0} 现已设为私密"
+
+msgid "{0} is plain text now"
+msgstr "{0} 现已设为纯文本"
+
+msgid "{0} changed kind"
+msgstr "{0} 已更改类型"
+
+msgid "{0} converted, {1} moved to the things' notes."
+msgstr "已转换 {0} 项,另有 {1} 项移至物品备注。"
+
+msgid "Make secret"
+msgstr "设为私密"
+
+msgid "Make plain"
+msgstr "设为普通字段"
+
+msgid "Change kind"
+msgstr "更改类型"
+
+msgid "Now: {0}"
+msgstr "当前:{0}"
+
+msgid "Separate the choices with commas. A value that isn't one of them goes to the notes."
+msgstr "用逗号分隔各选项。不符合任何选项的值将放入备注。"
+
+msgid "Past history keeps that the value changed, but no longer the value."
+msgstr "历史记录会保留“该值曾被修改”的痕迹,但不再保留具体数值。"
+
+msgid "Exports made before now still hold it."
+msgstr "此前生成的导出文件仍包含该内容。"
+
+msgid "Its values show to everyone who can see the thing, and history keeps them from now on."
+msgstr "所有能查看此物品的人均可看到其估值,且历史记录从现在起会保留这些数值。"
+
+msgid "Secrets are values Kept must be able to recover. Save the recovery kit on the status page, then make the field secret again."
+msgstr "加密字段属于 Kept 必须能够恢复的数据。请先在状态页面保存恢复套件,然后再将该字段设为加密。"
+
+msgid "The person who runs this server needs to save the recovery kit before secrets can be kept. Ask them, then make the field secret again."
+msgstr "服务器管理员需先保存恢复工具包,才能保存私密字段。请联系管理员处理,然后再将该字段设为私密。"
+
+msgid "Type {0} to confirm"
+msgstr "输入 {0} 以确认"
+
+msgid "This can't be undone."
+msgstr "此操作无法撤销。"
+
+msgid "Nothing holds a value yet: only the field changes."
+msgstr "目前尚无物品填写该值,因此仅修改字段本身。"
+
+msgid "What changes, by location"
+msgstr "各空间变更内容"
+
+msgid "A location you can't see"
+msgstr "你无权查看的空间"
+
+msgid "{0, plural, one {# value moves to secrets} other {# values move to secrets}}"
+msgstr "{0, plural, one {# 个值将移至私密字段} other {# 个值将移至私密字段}}"
+
+msgid "{0, plural, one {# value becomes plain text} other {# values become plain text}}"
+msgstr "{0, plural, one {# 个值将转为纯文本} other {# 个值将转为纯文本}}"
+
+msgid "{0, plural, one {# converts} other {# convert}}"
+msgstr "{0, plural, one {# 项可转换} other {# 项可转换}}"
+
+msgid "{0, plural, one {# goes to the notes} other {# go to the notes}}"
+msgstr "{0, plural, one {# 项写入备注} other {# 项写入备注}}"
+
+msgid "Adjust"
+msgstr "调整"
+
+msgid "Low stock"
+msgstr "库存不足"
+
+msgid "Keep at least"
+msgstr "至少保留"
+
+msgid "Minimum to keep changed"
+msgstr "已更改最低保有量"
+
+msgid "Field converted"
+msgstr "字段已转换"
+
+msgid "List exported as a CSV"
+msgstr "已将列表导出为 CSV"
+
+msgid "File imported"
+msgstr "文件已导入"
+
+msgid "This list holds things from more than one account. Filter it to one location to print it."
+msgstr "此列表包含来自多个账户的物品。请先筛选为单个空间再打印。"
+
+msgid "Low"
+msgstr "偏低"
+
+msgid "Things you run out of is off in your locations"
+msgstr "你的空间尚未开启消耗品功能"
+
+msgid "Search consumables"
+msgstr "搜索消耗品"
+
+msgid "Low or enough"
+msgstr "库存不足或充足"
+
+msgid "by stock"
+msgstr "按库存"
+
+msgid "Enough"
+msgstr "充足"
+
+msgid "Nothing to keep stocked yet"
+msgstr "暂无需要补货的常备物品"
+
+msgid "On a thing you run out of, such as batteries or filters, set \"Keep at least\", and it shows here, low first."
+msgstr "对于电池、滤芯等消耗品,设置「至少保留」数量后,系统会在此按库存从低到高显示。"
+
+msgid "Things you run out of is off in this location"
+msgstr "此空间已关闭「消耗品」追踪"
+
+msgid "Turn it on under What to track to keep a minimum of things you use up."
+msgstr "在「追踪内容」中开启后,即可为消耗品设置最低保有量。"
+
+msgid "Ask an owner or admin of this location to turn it on."
+msgstr "请联系此空间的所有者或管理员开启该功能。"
+
+msgid "Adjust {name}"
+msgstr "调整 {name}"
+
+msgid "Adjust {0}"
+msgstr "调整 {0}"
+
+msgid "A number, 0 or more."
+msgstr "请输入大于或等于 0 的数字。"
+
+msgid "A number above 0, or empty for no minimum."
+msgstr "大于 0 的数字,留空表示不设下限。"
+
+msgid "Adjusted {0}"
+msgstr "已调整 {0}"
+
+msgid "How many are left"
+msgstr "剩余数量"
+
+msgid "Below this it's listed as low. Empty for no minimum."
+msgstr "低于此数量时将标记为低库存。留空表示不设下限。"
+
+msgid "{quantity, plural, one {# left} other {# left}}"
+msgstr "{quantity, plural, one {剩余 #} other {剩余 #}}"
+
+msgid "keep at least {minText}"
+msgstr "至少保留 {minText}"
+
+msgid "Set a minimum"
+msgstr "设置最低库存"
+
+msgid "No minimum. Set one and Kept lists it as low when fewer are left."
+msgstr "未设下限。设置后,当剩余数量低于该值时 Kept 会将其列入库存不足。"
+
+msgid "One file per location: everything in it, the original photos and documents, and a copy you can read without Kept. Import it into this Kept or another one."
+msgstr "每个空间导出为一个文件:包含所有数据、原始照片与文档,以及无需 Kept 即可阅读的副本。可导入回当前或另一个 Kept 实例。"
+
+msgid "Export a location"
+msgstr "导出空间"
+
+msgid "Export my data"
+msgstr "导出我的数据"
+
+msgid "Each download link is made when you click Download and lasts 5 minutes; Kept checks you're still an owner or admin every time. Exports are kept 7 days."
+msgstr "每次点击「下载」都会生成有效期为 5 分钟的下载链接,且 Kept 每次都会校验你是否仍为拥有者或管理员。导出文件保留 7 天。"
+
+msgid "Your data"
+msgstr "你的数据"
+
+msgid "Choose where to import it first."
+msgstr "请先选择要导入到的空间。"
+
+msgid "Someone changed this import in the meantime. It has been reloaded; check it and try again."
+msgstr "在此期间有人修改了此导入任务,页面已重新加载;请核对后再试。"
+
+msgid "Kept can't read this archive"
+msgstr "Kept 无法读取该压缩包"
+
+msgid "Nothing was imported"
+msgstr "未导入任何内容"
+
+msgid "It isn't an export Kept can read. Export it again and try once more."
+msgstr "Kept 无法读取此导出文件。请重新导出后再试一次。"
+
+msgid "Choose another file"
+msgstr "选择其他文件"
+
+msgid "The upload didn't finish"
+msgstr "上传未能完成"
+
+msgid "The file didn't arrive whole, so nothing was imported. Choose it again."
+msgstr "文件未能完整上传,未导入任何内容。请重新选择文件。"
+
+msgid "Choose the file again"
+msgstr "重新选择文件"
+
+msgid "What's in it"
+msgstr "内部物品"
+
+msgid "Reading the archive…"
+msgstr "正在读取压缩包…"
+
+msgid "A few choices, before the check"
+msgstr "校验前的几项设置"
+
+msgid "The check reads the whole export the way the import will, and changes nothing. It shows what would be added, which printed labels keep their codes, and what can't come across."
+msgstr "预检会按真实导入方式读取整个导出包,且不会修改任何数据。它会展示将新增哪些内容、哪些已打印标签会保留原编码,以及哪些内容无法导入。"
+
+msgid "Importing into <0>{name}0>"
+msgstr "正在导入到 <0>{name}0>"
+
+msgid "{done} of {of}"
+msgstr "{done} / {of}"
+
+msgid "Resume to carry on where it stopped"
+msgstr "恢复以从上次中断处继续"
+
+msgid "What it already imported stays; nothing is made twice."
+msgstr "已导入的内容会保留;不会重复创建。"
+
+msgid "It stops after what it's working on. What it already imported stays; import the same export again later and that is skipped."
+msgstr "将在当前条目处理完成后停止。已导入的内容会保留;后续再次导入同一导出文件时会自动跳过已导入项。"
+
+msgid "What it imported before stopping stays in <0>{name}0>."
+msgstr "停止前已导入的内容仍保留在 <0>{name}0> 中。"
+
+msgid "Imported into <0>{name}0>"
+msgstr "已导入到 <0>{name}0>"
+
+msgid "See what was imported"
+msgstr "查看已导入内容"
+
+msgid "Open the location"
+msgstr "打开空间"
+
+msgid "Import something else"
+msgstr "导入其他数据"
+
+msgid "{0, plural, one {# thing} other {# things}}, {1, plural, one {# place} other {# places}} and {files, plural, one {# file} other {# files}}."
+msgstr "{0, plural, one {# 件物品} other {# 件物品}}、{1, plural, one {# 个位置} other {# 个位置}}和 {files, plural, one {# 个文件} other {# 个文件}}。"
+
+msgid "{labels, plural, one {# old Homebox label opens its thing here now.} other {# old Homebox labels open their things here now.}}"
+msgstr "{labels, plural, one {已有 # 个旧 Homebox 标签在此对应到相应物品。} other {已有 # 个旧 Homebox 标签在此对应到相应物品。}}"
+
+msgid "{labels, plural, one {# printed label opens its thing here now.} other {# printed labels open their things here now.}}"
+msgstr "{labels, plural, one {# 张已打印标签现在可在此打开对应物品。} other {# 张已打印标签现在可在此打开对应物品。}}"
+
+msgid "Choose the .zip file the export made."
+msgstr "选择导出生成的 .zip 文件。"
+
+msgid "This file is empty."
+msgstr "此文件为空。"
+
+msgid "This file is {bytes}; an import takes at most {gb} GB."
+msgstr "此文件大小为 {bytes};单次导入最大支持 {gb} GB。"
+
+msgid "Stop the upload?"
+msgstr "要停止上传吗?"
+
+msgid "Nothing has been imported yet. To import this file later, choose it again."
+msgstr "尚未导入任何内容。如需稍后导入此文件,请重新选择它。"
+
+msgid "Stop and leave"
+msgstr "停止并退出"
+
+msgid "Keep uploading"
+msgstr "继续上传"
+
+msgid "Needs a connection. Choose the file again when you're back online."
+msgstr "需要联网。请在恢复网络后重新选择文件。"
+
+msgid "This archive is too large to import."
+msgstr "此压缩包过大,无法导入。"
+
+msgid "The file changed while it was being sent. Choose it again."
+msgstr "文件在发送过程中发生变动,请重新选择。"
+
+msgid "This file can't be read any more. Choose it again."
+msgstr "此文件已无法读取,请重新选择。"
+
+msgid "The Homebox export"
+msgstr "Homebox 导出文件"
+
+msgid "The Kept export"
+msgstr "Kept 导出文件"
+
+msgid "Checking the file"
+msgstr "正在检查文件"
+
+msgid "Checking it on this device{0}{percent}%"
+msgstr "正在此设备上检查{0}{percent}%"
+
+msgid "Uploading{0}{percent}%"
+msgstr "正在上传{0}{percent}%"
+
+msgid "Up to 5 GB. Nothing is imported until you've seen what's in it and checked it."
+msgstr "最大支持 5 GB。在你查看内容并确认之前,不会导入任何数据。"
+
+msgid "Choose the .zip file"
+msgstr "选择 .zip 文件"
+
+msgid "If Homebox says \"Topic has been Shutdown\""
+msgstr "如果 Homebox 提示「Topic has been Shutdown」"
+
+msgid "A Kept export always comes in as a new location, with its photos, documents, history and printed labels."
+msgstr "从 Kept 导出的文件始终会作为新空间导入,并保留原有照片、文档、历史记录和已打印标签。"
+
+msgid "Adding search words"
+msgstr "正在添加搜索关键词"
+
+msgid "It runs in the background; the things gain their words over the next minutes."
+msgstr "该任务在后台运行;接下来的几分钟内物品会陆续生成检索词。"
+
+msgid "Add search words with AI?"
+msgstr "使用 AI 添加搜索关键词?"
+
+msgid "Words in each of the location's languages for every imported thing, so \"drill\" finds \"Bosch GSB 18V\"."
+msgstr "为每件导入的物品补充该空间所用语言的关键词,这样搜索「电钻」也能找到「Bosch GSB 18V」。"
+
+msgid "about {tokens} tokens"
+msgstr "约 {tokens} tokens"
+
+msgid "Add search words"
+msgstr "添加搜索关键词"
+
+msgid "{0, plural, one {photo or file} other {photos and files}}"
+msgstr "{0, plural, =1 {张照片或文件} other {张照片与文件}}"
+
+msgid "{0, plural, one {old label kept} other {old labels kept}}"
+msgstr "{0, plural, one {个旧标签已保留} other {个旧标签已保留}}"
+
+msgid "{0, plural, one {label kept as printed} other {labels kept as printed}}"
+msgstr "{0, plural, one {张标签保留为已打印状态} other {张标签保留为已打印状态}}"
+
+msgid "{0, plural, one {label with a new code (the old one still opens it)} other {labels with a new code (the old ones still open them)}}"
+msgstr "{0, plural, one {个使用新编码的标签(旧标签仍可打开)} other {个使用新编码的标签(旧标签仍可打开)}}"
+
+msgid "{0, plural, one {history event} other {history events}}"
+msgstr "{0, plural, one {条历史记录} other {条历史记录}}"
+
+msgid "Everything maps as it is: nothing needs a look."
+msgstr "所有项均可直接映射:无需人工核对。"
+
+msgid "Needs a look"
+msgstr "需要查看"
+
+msgid "{total, plural, one {(# entry)} other {(# entries)}}"
+msgstr "{total, plural, one {(# 条记录)} other {(# 条记录)}}"
+
+msgid "Search the report"
+msgstr "搜索报告"
+
+msgid "A name or a reason"
+msgstr "名称或原因"
+
+msgid "From the connection to Homebox. Choosing another relabels the amounts; it doesn't convert them."
+msgstr "来自与 Homebox 的连接。选择其他货币只会重标金额单位,不会换算数值。"
+
+msgid "Homebox's export has no currency. Choosing one relabels the amounts; it doesn't convert them."
+msgstr "Homebox 导出文件不包含币种。选择币种仅重新标注金额单位,不会进行汇率换算。"
+
+msgid "Homebox's currency, <0>{fromConnection}0>, isn't turned on in Kept. An instance admin can turn it on in Admin → Currencies."
+msgstr "Homebox 使用的货币 <0>{fromConnection}0> 尚未在 Kept 中启用。实例管理员可在“管理 → 货币”中开启。"
+
+msgid "This location counts in <0>{locationCurrency}0>; prices in another currency are kept as they are."
+msgstr "此空间使用 <0>{locationCurrency}0> 计价;其他货币的价格将保持原样显示。"
+
+msgid "Archived items"
+msgstr "已归档物品"
+
+msgid "Leave out"
+msgstr "排除此项"
+
+msgid "Add an \"Insured\" yes/no field"
+msgstr "添加「已投保」是/否字段"
+
+msgid "{insured, plural, one {# item is marked insured.} other {# items are marked insured.}}"
+msgstr "{insured, plural, one {# 件物品已标记为已投保。} other {# 件物品已标记为已投保。}}"
+
+msgid "Leave out Homebox's starter places and tags"
+msgstr "排除 Homebox 的初始示例位置和分类标签"
+
+msgid "Only the empty ones: <0>{seededList}0>."
+msgstr "仅限空项:<0>{seededList}0>。"
+
+msgid "Custom fields"
+msgstr "自定义字段"
+
+msgid "{0, plural, one {on # item} other {on # items}}"
+msgstr "{0, plural, one {涉及 # 件物品} other {涉及 # 件物品}}"
+
+msgid "What happens to {0}"
+msgstr "如何处理 {0}"
+
+msgid "Add to the type"
+msgstr "添加到该类型"
+
+msgid "Keep in notes"
+msgstr "保留在备注中"
+
+msgid "Homebox's types are matched to Kept's by name, and its custom fields are added to their types. The check shows what that does before anything is imported."
+msgstr "Homebox 的类型会按名称匹配到 Kept 的类型,其自定义字段也会添加到对应类型中。开始导入前,检查结果会先展示这些改动。"
+
+msgid "number"
+msgstr "数值"
+
+msgid "yes or no"
+msgstr "是或否"
+
+msgid "date"
+msgstr "日期"
+
+msgid "text"
+msgstr "文本"
+
+msgid "A Kept type"
+msgstr "Kept 物品类型"
+
+msgid "Homebox types"
+msgstr "Homebox 类型"
+
+msgid "Search Homebox types"
+msgstr "搜索 Homebox 类型"
+
+msgid "{0, plural, one {# item} other {# items}}"
+msgstr "{0, plural, one {# 件物品} other {# 件物品}}"
+
+msgid "Kept type for {name}"
+msgstr "对应 {name} 的 Kept 类型"
+
+msgid "{0, plural, one {item or location} other {items and locations}}"
+msgstr "{0, plural, =1 {项物品或空间} other {项物品与空间}}"
+
+msgid "{0, plural, one {maintenance entry} other {maintenance entries}}"
+msgstr "{0, plural, one {条维护记录} other {条维护记录}}"
+
+msgid "The Homebox collection <0>{0}0>"
+msgstr "Homebox 集合 <0>{0}0>"
+
+msgid "One Homebox collection"
+msgstr "单个 Homebox 合集"
+
+msgid "exported {0}"
+msgstr "导出于 {0}"
+
+msgid "version <0>{version}0>"
+msgstr "版本 <0>{version}0>"
+
+msgid "version unknown"
+msgstr "版本未知"
+
+msgid "That address is on a private network. An instance admin can allow private addresses in Admin → Settings."
+msgstr "该地址位于内网。实例管理员可在「管理 → 设置」中允许访问内网地址。"
+
+msgid "Check the address: it starts with http:// or https://."
+msgstr "请检查地址:必须以 http:// 或 https:// 开头。"
+
+msgid "Homebox didn't accept that. Check the address and the sign-in details."
+msgstr "Homebox 未接受该请求。请检查地址和登录信息。"
+
+msgid "Connected to Homebox"
+msgstr "已连接到 Homebox"
+
+msgid "prices in <0>{0}0>"
+msgstr "以 <0>{0}0> 计价"
+
+msgid "{members, plural, one {# member} other {# members}}"
+msgstr "{members, plural, one {# 位成员} other {# 位成员}}"
+
+msgid "Connect to Homebox (optional)"
+msgstr "连接到 Homebox(可选)"
+
+msgid "Reads the version, the collection's currency and its members. Used once, never stored."
+msgstr "读取版本、收藏集币种及成员信息。仅使用一次,从不保存。"
+
+msgid "Connect"
+msgstr "连接"
+
+msgid "Homebox address"
+msgstr "Homebox 地址"
+
+msgid "Sign in with"
+msgstr "使用以下方式登录"
+
+msgid "API key"
+msgstr "API 密钥"
+
+msgid "Email and password"
+msgstr "邮箱与密码"
+
+msgid "Used once to read Homebox, never stored."
+msgstr "仅用于读取一次 Homebox 数据,不会保存。"
+
+msgid "Couldn't connect"
+msgstr "无法连接"
+
+msgid "A Kept <0>{0}0> export{1}{2}"
+msgstr "一份 Kept <0>{0}0> 导出文件{1}{2}"
+
+msgid "{0, plural, one {event in the history} other {events in the history}}"
+msgstr "{0, plural, one {条历史记录事件} other {条历史记录事件}}"
+
+msgid "That passphrase doesn't open this export's secrets."
+msgstr "该密码短语无法解开此导出文件中的私密数据。"
+
+msgid "Too many tries. Try again in an hour."
+msgstr "尝试次数过多,请一小时后再试。"
+
+msgid "The secrets will be imported"
+msgstr "敏感密钥信息也会一并导入"
+
+msgid "The passphrase opened them. They stay encrypted until the import writes them."
+msgstr "口令验证成功。在导入正式写入前,这些内容将保持加密状态。"
+
+msgid "It holds encrypted secrets"
+msgstr "其中包含加密的私密字段"
+
+msgid "Enter the passphrase chosen when it was exported to import them too. Without it, everything else is imported."
+msgstr "输入导出时设置的密码短语即可一并导入私密数据;留空则仅导入其余内容。"
+
+msgid "Passphrase"
+msgstr "密码短语"
+
+msgid "Open the secrets"
+msgstr "解锁私密信息"
+
+msgid "People to invite"
+msgstr "邀请对象"
+
+msgid "Nobody is invited by the import: invite each person yourself, with their email."
+msgstr "导入不会自动邀请任何人:请通过邮箱自行逐一邀请。"
+
+msgid "Not imported: a file type Kept doesn't keep."
+msgstr "未导入:Kept 不支持保存此类文件。"
+
+msgid "The file isn't in the archive, so it's left out."
+msgstr "归档包中没有此文件,因此未导入。"
+
+msgid "The file is larger than Kept takes, so it's left out."
+msgstr "文件超过了 Kept 的大小上限,因此未导入。"
+
+msgid "Not something Kept reads from an export; ignored."
+msgstr "Kept 不从导出文件中读取该项,已忽略。"
+
+msgid "Archived in Homebox, left out."
+msgstr "在 Homebox 中已归档,未导入。"
+
+msgid "Counted one by one in Kept; Homebox's quantity is kept in the notes."
+msgstr "在 Kept 中将按件单独计数;Homebox 原有的数量已保存在备注中。"
+
+msgid "Homebox keeps numbers whole, so any decimals were already lost there."
+msgstr "Homebox 仅保存整数,因此其中的小数部分在原有数据中就已舍去。"
+
+msgid "Kept has no icon like Homebox's; the type's own icon is used."
+msgstr "Kept 中没有与 Homebox 对应的图标,已改用该类型自身的图标。"
+
+msgid "A Kept template can't hold money or secrets; the rest of the template is imported."
+msgstr "Kept 模板不能包含金额或私密字段;模板的其余部分已导入。"
+
+msgid "This currency isn't turned on in Kept; the prices are kept in the notes."
+msgstr "Kept 中未启用此货币;价格已保留在备注中。"
+
+msgid "Kept can't hold this record yet; its text is kept in the thing's notes."
+msgstr "Kept 暂不支持该记录格式;其文本已保存在物品备注中。"
+
+msgid "Notifiers are never imported: their addresses can hold passwords."
+msgstr "通知渠道不会被导入:其地址中可能包含密码。"
+
+msgid "One of Homebox's starter places or tags, empty and unused, left out."
+msgstr "Homebox 自带的空白初始位置或分类标签,未使用,已略过。"
+
+msgid "A date Homebox filled in with the day the item was made; read as empty."
+msgstr "Homebox 自动以物品创建日期填充了该日期,导入时视为空值。"
+
+msgid "It holds more than {n} files."
+msgstr "包含超过 {n} 个文件。"
+
+msgid "It's larger than {gb} GB."
+msgstr "文件大小超过了 {gb} GB。"
+
+msgid "One of its files unpacks to far more than its size, the way a booby-trapped archive does."
+msgstr "其中某个文件解压后的体积远大于原始大小,存在压缩炸弹风险。"
+
+msgid "It holds a link to somewhere outside the archive."
+msgstr "它包含指向归档包外部的链接。"
+
+msgid "One of its file names points outside the archive."
+msgstr "压缩包中的某个文件名指向归档目录之外。"
+
+msgid "Two of its files have the same name."
+msgstr "其中有两个文件同名。"
+
+msgid "It's incomplete: the download or the copy stopped before the end."
+msgstr "内容不完整:下载或复制在结束前中断了。"
+
+msgid "It's from a newer version than this Kept reads. Update Kept, then import it."
+msgstr "它来自更新的版本,当前 Kept 无法读取。请先更新 Kept 再导入。"
+
+msgid "It's protected with a ZIP password, which Kept can't open. Export it again without one."
+msgstr "该 ZIP 文件受密码保护,Kept 无法打开。请取消密码后重新导出。"
+
+msgid "One of its data files is too large to read."
+msgstr "其中的一个数据文件过大,无法读取。"
+
+msgid "One thing per row, with a header row naming the columns."
+msgstr "每行一件物品,第一行为标注列名的表头行。"
+
+msgid "A Homebox export"
+msgstr "Homebox 导出文件"
+
+msgid "A Kept export"
+msgstr "Kept 导出文件"
+
+msgid "A location exported from this Kept or another one. It comes in as a new location."
+msgstr "从本 Kept 或其他 Kept 实例导出的空间。导入后将作为新空间。"
+
+msgid "Give the new location a name."
+msgstr "请给新空间起个名字。"
+
+msgid "Its timezone and currency are this device's; change them later in Location settings."
+msgstr "默认采用此设备的时区和币种;之后可在「空间设置」中更改。"
+
+msgid "A new location"
+msgstr "新建空间"
+
+msgid "Made in your account, with its own Unplaced area."
+msgstr "已在你的账号下创建,并配有独立的「未放置」区域。"
+
+msgid "A Kept export always comes in as a new location."
+msgstr "Kept 导出包在导入时始终会创建为一个新空间。"
+
+msgid "A location you run"
+msgstr "由你管理的空间"
+
+msgid "<0>{names}0>. Things already there stay; importing the same export again adds only what's new."
+msgstr "<0>{names}0>。已有的物品会保留;再次导入同一份导出文件只会添加新增内容。"
+
+msgid "Deleting <0>{name}0> removes it for everyone in it. It stays restorable for 30 days."
+msgstr "删除 <0>{name}0> 将使所有成员都无法访问。30 天内可恢复。"
+
+msgid "Delete <0>{name}0>…"
+msgstr "删除 <0>{name}0>…"
+
+msgid "Deleted {0}. It can be restored for 30 days."
+msgstr "已删除 {0}。30 天内可恢复。"
+
+msgid "Delete <0>{name}0>?"
+msgstr "删除 <0>{name}0>?"
+
+msgid "Type {name} to confirm"
+msgstr "输入 {name} 以确认"
+
+msgid "That isn't the location's name."
+msgstr "这与空间名称不一致。"
+
+msgid "<0>{name}0> stays restorable for 30 days, then it's gone with its files."
+msgstr "<0>{name}0> 将可恢复保留 30 天,之后会连同文件一并永久删除。"
+
+msgid "Delete <0>{name}0>"
+msgstr "删除 <0>{name}0>"
+
+msgid "Export first"
+msgstr "先导出"
+
+msgid "A copy of everything in <0>{name}0>, its files and a readable copy, before it goes."
+msgstr "删除前导出的完整备份:包含 <0>{name}0> 中的所有数据、文件以及一份可读副本。"
+
+msgid "Exporting…"
+msgstr "正在导出…"
+
+msgid "Exported"
+msgstr "已导出"
+
+msgid "The export didn't finish"
+msgstr "导出未完成"
+
+msgid "My data"
+msgstr "我的数据"
+
+msgid "A location you no longer run"
+msgstr "你已不再管理的空间"
+
+msgid "Exports"
+msgstr "导出记录"
+
+msgid "Search exports"
+msgstr "搜索导出记录"
+
+msgid "No exports yet"
+msgstr "暂无导出记录"
+
+msgid "Each export is kept here for seven days after it's ready."
+msgstr "每个导出包生成后将在此处保留 7 天。"
+
+msgid "This export has expired. Export again for a new one."
+msgstr "此导出文件已过期,请重新导出。"
+
+msgid "Started {0}{1}{done} of {total}"
+msgstr "已开始 {0}{1}{done} / {total}"
+
+msgid "Asked for {0}"
+msgstr "已请求 {0}"
+
+msgid "Ready {0}"
+msgstr "就绪 {0}"
+
+msgid "until {0}"
+msgstr "至 {0}"
+
+msgid "Made {0}"
+msgstr "创建于 {0}"
+
+msgid "with secrets"
+msgstr "含私密字段"
+
+msgid "Download the export of {name}"
+msgstr "下载 {name} 的导出包"
+
+msgid "Export again"
+msgstr "重新导出"
+
+msgid "What goes in"
+msgstr "要装入的内容"
+
+msgid "Every thing, place, photo and document is always in it."
+msgstr "所有物品、位置、照片和文档都属于且仅属于一个空间。"
+
+msgid "Ended things (sold, given away, thrown out)"
+msgstr "已结束使用的物品(已售出、已赠送、已丢弃)"
+
+msgid "Things in the Trash"
+msgstr "回收站中的物品"
+
+msgid "A copy you can read without Kept"
+msgstr "无需 Kept 即可直接阅读的副本"
+
+msgid "with the inventory PDF"
+msgstr "随资产清单 PDF 一并提供"
+
+msgid "The readable copy's language"
+msgstr "可读副本的语言"
+
+msgid "Its digits"
+msgstr "其数字"
+
+msgid "Include secrets"
+msgstr "包含私密字段"
+
+msgid "Encrypted with a passphrase you choose. The readable copy never holds them."
+msgstr "使用你设置的口令加密。可读副本中绝不包含这些内容。"
+
+msgid "Anyone with this file and the passphrase can read every secret in it. Kept can't recover a forgotten passphrase."
+msgstr "任何拥有此文件与口令的人都能读取其中的全部密钥信息。若忘记口令,Kept 将无法找回。"
+
+msgid "Export <0>{name}0>"
+msgstr "导出 <0>{name}0>"
+
+msgid "Waiting"
+msgstr "等待中"
+
+msgid "Exporting"
+msgstr "正在导出"
+
+msgid "Ready"
+msgstr "已就绪"
+
+msgid "Failed"
+msgstr "失败"
+
+msgid "the server ran out of space"
+msgstr "服务器存储空间不足"
+
+msgid "you're no longer an owner or admin there"
+msgstr "你已不再是该空间的所有者或管理员"
+
+msgid "the server restarted while it ran"
+msgstr "服务器在运行期间重启"
+
+msgid "it stopped before the end"
+msgstr "提前中断"
+
+msgid "An export of this location is already running."
+msgstr "此空间的导出任务已在运行中。"
+
+msgid "Five exports an hour at most. Try again a little later."
+msgstr "每小时最多导出 5 次,请稍后再试。"
+
+msgid "Secrets leave Kept only once the recovery kit is saved. An instance admin saves it from the status page."
+msgstr "仅当保存恢复工具包后,私密数据才会允许导出备份。实例管理员可在状态页保存恢复工具包。"
+
+msgid "Use a passphrase of at least 12 characters, the same both times."
+msgstr "请使用至少 12 个字符的口令,并确保两次输入一致。"
+
+msgid "Only owners and admins export a location; only its owner includes secrets."
+msgstr "仅所有者与管理员可导出空间;仅所有者导出时可包含加密字段。"
+
+msgid "At least {min} characters."
+msgstr "至少需要 {min} 个字符。"
+
+msgid "The passphrase again"
+msgstr "再次输入口令"
+
+msgid "The two passphrases are different."
+msgstr "两次输入的密码短语不一致。"
+
+msgid "{0, plural, one {warranty to add} other {warranties to add}}"
+msgstr "{0, plural, one {条待添加保修} other {条待添加保修}}"
+
+msgid "{0, plural, one {service to add} other {services to add}}"
+msgstr "{0, plural, one {条待添加的保养记录} other {条待添加的保养记录}}"
+
+msgid "{0, plural, one {type to add} other {types to add}}"
+msgstr "{0, plural, one {种类型待添加} other {种类型待添加}}"
+
+msgid "{0, plural, one {secret to bring over} other {secrets to bring over}}"
+msgstr "{0, plural, one {个待导入的私密字段} other {个待导入的私密字段}}"
+
+msgid "{0, plural, one {attachment in it} other {attachments in it}}"
+msgstr "{0, plural, one {个附件} other {个附件}}"
+
+msgid "{0, plural, one {tag in it} other {tags in it}}"
+msgstr "{0, plural, one {个分类标签} other {个分类标签}}"
+
+msgid "{0, plural, one {thing in it} other {things in it}}"
+msgstr "{0, plural, one {件内含物品} other {件内含物品}}"
+
+msgid "{0, plural, one {place in it} other {places in it}}"
+msgstr "{0, plural, one {个内部位置} other {个内部位置}}"
+
+msgid "{0, plural, one {file in it} other {files in it}}"
+msgstr "{0, plural, one {个内部文件} other {个内部文件}}"
+
+msgid "{0, plural, one {Reading is # day old} other {Reading is # days old}}"
+msgstr "{0, plural, one {读数已距今 # 天} other {读数已距今 # 天}}"
+
+msgid "{0, plural, one {# full month} other {# full months}}"
+msgstr "{0, plural, one {# 个整月} other {# 个整月}}"
+
+msgid "{0} so far"
+msgstr "目前已 {0}"
+
+msgid "{0}, by <0>{1}0>"
+msgstr "{0},由 <0>{1}0> 操作"
+
+msgid "{ageDays, plural, one {Estimates use the reading from # day ago.} other {Estimates use the reading from # days ago.}}"
+msgstr "{ageDays, plural, one {估算基于 # 天前的读数。} other {估算基于 # 天前的读数。}}"
+
+msgid "{ageDays, plural, one {Last reading # day ago, {day}} other {Last reading # days ago, {day}}}"
+msgstr "{ageDays, plural, one {上次读数 # 天前,{day}} other {上次读数 # 天前,{day}}}"
+
+msgid "{ageDays, plural, one {read # day ago} other {read # days ago}}"
+msgstr "{ageDays, plural, one {读取于 # 天前} other {读取于 # 天前}}"
+
+msgid "{ago, plural, one {{name} ran out # day ago} other {{name} ran out # days ago}}"
+msgstr "{ago, plural, one {{name} 已在 # 天前用完} other {{name} 已在 # 天前用完}}"
+
+msgid "{days, plural, one {{name} due in # day, on {day}} other {{name} due in # days, on {day}}}"
+msgstr "{days, plural, one {{name} 将于 # 天后到期({day})} other {{name} 将于 # 天后到期({day})}}"
+
+msgid "{days, plural, one {{name} due in # day} other {{name} due in # days}}"
+msgstr "{days, plural, one {{name} 将于 # 天后到期} other {{name} 将于 # 天后到期}}"
+
+msgid "{days, plural, one {About {perDay} {unit} a day over the last # day} other {About {perDay} {unit} a day over the last # days}}"
+msgstr "{days, plural, one {过去 # 天日均约 {perDay} {unit}} other {过去 # 天日均约 {perDay} {unit}}}"
+
+msgid "{n, plural, one {Added # schedule} other {Added # schedules}}"
+msgstr "{n, plural, one {已添加 # 个计划} other {已添加 # 个计划}}"
+
+msgid "{name} · at {at}"
+msgstr "{name} · 于 {at}"
+
+msgid "{name} · at {at} · reading needed"
+msgstr "{name} · 位于 {at} · 需要读数"
+
+msgid "{name} · due {day}"
+msgstr "{name} · 应还 {day}"
+
+msgid "{name} · estimated ~{day}"
+msgstr "{name} · 预计约 {day}"
+
+msgid "{name} · reading needed"
+msgstr "{name} · 需要抄表读数"
+
+msgid "{name} ran out on {day}"
+msgstr "{name} 已于 {day} 用完"
+
+msgid "{name} runs out today"
+msgstr "{name} 今日到期"
+
+msgid "{name}, {unit}"
+msgstr "{name},{unit}"
+
+msgid "A car, a motorbike or a generator: Kept keeps its odometer, what's due, fuel and running costs."
+msgstr "汽车、摩托车或发电机:Kept 可记录其里程表、待办保养、加油和养车费用。"
+
+msgid "Accepted"
+msgstr "已接受"
+
+msgid "Add a vehicle"
+msgstr "添加车辆"
+
+msgid "Add an odometer in its Details, and its readings show here."
+msgstr "在「详情」中添加里程表后,其读数就会显示在这里。"
+
+msgid "Add starter schedules"
+msgstr "添加预设入门计划"
+
+msgid "Air filter"
+msgstr "空气滤清器"
+
+msgid "All {0}"
+msgstr "全部 {0}"
+
+msgid "All readings"
+msgstr "全部读数"
+
+msgid "An owner or admin decides whether viewers see money here."
+msgstr "由所有者或管理员决定查看者是否可在此查看金额。"
+
+msgid "Bicycle"
+msgstr "自行车"
+
+msgid "Brake fluid"
+msgstr "制动液"
+
+msgid "Car"
+msgstr "汽车"
+
+msgid "Completed: {0}"
+msgstr "已完成:{0}"
+
+msgid "Costs are hidden in this location"
+msgstr "此空间已隐藏费用信息"
+
+msgid "Couldn't add them"
+msgstr "无法添加"
+
+msgid "Distance, {period}"
+msgstr "距离,{period}"
+
+msgid "Due soon"
+msgstr "即将到期"
+
+msgid "estimate at ~{perDay} {unit} a day"
+msgstr "按日均约 {perDay} {unit} 估算"
+
+msgid "estimated ~{day}"
+msgstr "预计约 {day}"
+
+msgid "Estimates use today's reading."
+msgstr "估算基于今天的读数。"
+
+msgid "Fees & insurance"
+msgstr "税费与保险"
+
+msgid "from a fill by {name}"
+msgstr "来自 {name} 的加油记录"
+
+msgid "from a photo by {name}"
+msgstr "来自 {name} 拍摄的照片"
+
+msgid "from a service by {name}"
+msgstr "来自 {name} 的维护服务"
+
+msgid "from the readings"
+msgstr "根据读数计算"
+
+msgid "Fuel, monthly average"
+msgstr "燃油月均费用"
+
+msgid "Generator"
+msgstr "发电机"
+
+msgid "Home Assistant"
+msgstr "Home Assistant"
+
+msgid "It has those already"
+msgstr "它已包含这些内容"
+
+msgid "Last reading"
+msgstr "上次读数"
+
+msgid "Last reading today, {day}"
+msgstr "上次读数:今天,{day}"
+
+msgid "Loading the costs"
+msgstr "正在加载费用数据"
+
+msgid "Loading the services"
+msgstr "正在加载服务列表"
+
+msgid "Motorbike"
+msgstr "摩托车"
+
+msgid "Newer"
+msgstr "较新"
+
+msgid "Next due"
+msgstr "下次到期"
+
+msgid "No documents yet: the licence, the insurance, the registration card."
+msgstr "暂无文档:可添加行驶证、保单、登记证等。"
+
+msgid "No full months yet."
+msgstr "尚无完整月份的数据。"
+
+msgid "No meter on this vehicle"
+msgstr "此车辆没有表计"
+
+msgid "No reading"
+msgstr "无读数"
+
+msgid "No reading yet"
+msgstr "暂无读数"
+
+msgid "No readings yet."
+msgstr "暂无读数。"
+
+msgid "No readings yet. Log the first one to start the estimates."
+msgstr "暂无读数。记录第一条读数后即可开始估算。"
+
+msgid "No vehicles yet"
+msgstr "暂无车辆"
+
+msgid "not compared with full months"
+msgstr "不参与完整月份对比"
+
+msgid "Nothing scheduled yet. Add the usual ones from the Schedules tab."
+msgstr "暂无计划。可在「计划」选项卡中添加常用维护计划。"
+
+msgid "Oil change"
+msgstr "更换机油"
+
+msgid "Older"
+msgstr "更早"
+
+msgid "or read its registration card in LABEL mode"
+msgstr "或在「标签」模式下拍摄其注册卡"
+
+msgid "over {distance} driven"
+msgstr "行驶超过 {distance}"
+
+msgid "Over {staleDays} days old"
+msgstr "已超过 {staleDays} 天"
+
+msgid "Over {unknownDays} days old"
+msgstr "超过 {unknownDays} 天"
+
+msgid "Overview"
+msgstr "概览"
+
+msgid "Part of a fill: change it there"
+msgstr "属于一次加油/充电记录:请在原记录中修改"
+
+msgid "Part of a service: change it there"
+msgstr "属于某个保养项目:请在对应项目中更改"
+
+msgid "Per {0}"
+msgstr "每 {0}"
+
+msgid "Proof photo"
+msgstr "凭证照片"
+
+msgid "Proof photo, {0}"
+msgstr "凭证照片,{0}"
+
+msgid "Proof photo, {0}, {1}"
+msgstr "凭证照片,{0},{1}"
+
+msgid "Read lately"
+msgstr "近期已读"
+
+msgid "read today"
+msgstr "今日已读"
+
+msgid "Reading, {unit}"
+msgstr "读数,{unit}"
+
+msgid "Readings over time"
+msgstr "读数变化趋势"
+
+msgid "Readings over time. Arrow keys move between readings."
+msgstr "读数随时间变化。可使用方向键在不同读数之间切换。"
+
+msgid "Recent services"
+msgstr "最近维护记录"
+
+msgid "Running cost per month, {currency}"
+msgstr "每月运行成本({currency})"
+
+msgid "Running cost per month. Arrow keys move between months and categories."
+msgstr "每月持有成本。可使用方向键在月份和分类之间切换。"
+
+msgid "Search vehicles"
+msgstr "搜索车辆"
+
+msgid "Service"
+msgstr "保养"
+
+msgid "Service & parts"
+msgstr "维护与配件"
+
+msgid "Start from the usual four: oil change, tyre rotation, brake fluid and air filter. Change or remove any of them later."
+msgstr "从常见的四项开始:更换机油、轮胎换位、刹车油和空气滤清器。之后可随时修改或移除。"
+
+msgid "Starter schedules"
+msgstr "预设入门计划"
+
+msgid "The dashboard"
+msgstr "仪表盘"
+
+msgid "The dashboard reading {value}"
+msgstr "仪表盘读数 {value}"
+
+msgid "The latest reading is too old to estimate from, so there are no estimated dates. Log a reading to bring them back."
+msgstr "最新读数过于久远,无法推算预计日期。记录一次新读数即可恢复预估。"
+
+msgid "The vehicles list comes from the server. Log a reading still works offline."
+msgstr "车辆列表来自服务器。「记录读数」在离线状态下仍可使用。"
+
+msgid "Total, {period}"
+msgstr "总计,{period}"
+
+msgid "Typed"
+msgstr "手动输入"
+
+msgid "typed by {name}"
+msgstr "由 {name} 输入"
+
+msgid "Tyre rotation"
+msgstr "轮胎换位"
+
+msgid "Unknown: reading needed"
+msgstr "未知:需要读数"
+
+msgid "Valid to {0}"
+msgstr "有效期至 {0}"
+
+msgid "Vehicle"
+msgstr "车辆"
+
+msgid "Vehicles is off in your locations"
+msgstr "你的所有空间均未开启车辆功能"
+
+msgid "Whichever comes first. These are common defaults, not your maker's advice: check the handbook and edit them to match."
+msgstr "以先到者为准。这些是常见默认值,并非厂商建议:请查阅手册并按需修改。"
+
+msgid "{at} · HTTP <0>{0}0> · {1, plural, one {# attempt} other {# attempts}}"
+msgstr "{at} · HTTP <0>{0}0> · {1, plural, one {# 次尝试} other {# 次尝试}}"
+
+msgid "{at} · no answer · {0, plural, one {# attempt} other {# attempts}}"
+msgstr "{at} · 无响应 · {0, plural, one {已尝试 # 次} other {已尝试 # 次}}"
+
+msgid "{got} of {size}"
+msgstr "{got} / {size}"
+
+msgid "{label}: {plain}"
+msgstr "{label}:{plain}"
+
+msgid "{name} can't reach your Kept any more"
+msgstr "{name} 已无法再访问你的 Kept"
+
+msgid "{scope} · <0>{where}0> · allowed {granted} · not used yet"
+msgstr "{scope} · <0>{where}0> · 授权于 {granted} · 尚未使用"
+
+msgid "{scope} · <0>{where}0> · allowed {granted} · used {used}"
+msgstr "{scope} · <0>{where}0> · 授权于 {granted} · 最近使用 {used}"
+
+msgid "{scope} · <0>{where}0> · expires {expires}"
+msgstr "{scope} · <0>{where}0> · 过期时间 {expires}"
+
+msgid "{scope} · <0>{where}0> · no expiry"
+msgstr "{scope} · <0>{where}0> · 永不过期"
+
+msgid "{scope} · <0>{where}0> · not used yet"
+msgstr "{scope} · <0>{where}0> · 尚未使用"
+
+msgid "{scope} · <0>{where}0> · used {used}"
+msgstr "{scope} · <0>{where}0> · 上次使用:{used}"
+
+msgid "<0>{name}0> wants to use your Kept"
+msgstr "<0>{name}0> 请求访问你的 Kept"
+
+msgid "<0>{who}0> hasn't confirmed your email address, so Kept can't use it. Confirm it there, then try again."
+msgstr "<0>{who}0> 尚未确认你的邮箱地址,因此 Kept 无法使用它。请先在那里确认,然后再试。"
+
+msgid "~{0} tokens"
+msgstr "约 {0} tokens"
+
+msgid "A local model on this server, no per-call cost"
+msgstr "此服务器上的本地模型,无按次调用费用"
+
+msgid "A meter reading is logged"
+msgstr "记录了表计读数"
+
+msgid "A reminder is due"
+msgstr "有提醒到期时"
+
+msgid "A Shortcut that asks for the reading and sends it to Kept with a token."
+msgstr "一个询问读数并通过令牌发送给 Kept 的快捷指令。"
+
+msgid "A signed message to your own server when things change here. It carries ids and the names of changed fields, never names, places or values."
+msgstr "当此处发生变更时,向你自己的服务器发送签名消息。消息仅包含 ID 和变更字段名,绝不携带名称、位置或数值。"
+
+msgid "A thing comes back from Trash"
+msgstr "物品从回收站还原"
+
+msgid "A thing goes to Trash"
+msgstr "物品移入回收站"
+
+msgid "A thing is added"
+msgstr "添加物品时"
+
+msgid "A thing is changed"
+msgstr "物品有变更时"
+
+msgid "A thing is moved"
+msgstr "物品被移动"
+
+msgid "A thing's state changes, such as lost or sold"
+msgstr "物品状态发生变化,例如丢失或售出"
+
+msgid "A token lets an app such as Claude Desktop, or a Shortcut on your phone, find and add your things. Make one for each app, limited to the locations it needs."
+msgstr "令牌可让 Claude Desktop 或手机快捷指令等应用查找并添加你的物品。建议为每个应用单独创建一个,并限制其仅访问所需的空间。"
+
+msgid "A token starts with one location. Add another only if the app needs both."
+msgstr "令牌默认仅授权一个空间。仅当应用确实需要访问多个空间时再添加。"
+
+msgid "A token that can change things in <0>{picks}0> lets an app move things between them, so people in one could see what came from the other. Make one token per location unless you mean that."
+msgstr "具备 <0>{picks}0> 修改权限的令牌可让应用在这些空间之间移动物品,因此某空间的人可能会看到来自另一空间的内容。除非确实需要,否则建议为每个空间单独创建令牌。"
+
+msgid "Add <0>Get Contents of URL0> with this address, and set its method to POST:"
+msgstr "添加<0>获取 URL 内容0>操作并填入此地址,将方法设为 POST:"
+
+msgid "Add one to tell a home server, Home Assistant or a script when a thing is added, moved or changed in this location."
+msgstr "添加一个 Webhook,在该空间内添加、移动或修改物品时通知家庭服务器、Home Assistant 或脚本。"
+
+msgid "Add webhook"
+msgstr "添加 Webhook"
+
+msgid "Add your car to Kept with an odometer reading first; its address appears here then."
+msgstr "请先在 Kept 中添加你的车辆并记录一条里程表读数,之后其快捷地址会显示在此处。"
+
+msgid "Added by <0>{0}0>"
+msgstr "由 <0>{0}0> 添加"
+
+msgid "Allow"
+msgstr "允许"
+
+msgid "Any MCP client"
+msgstr "任意 MCP 客户端"
+
+msgid "Anyone who can open the Shortcut on your phone can log readings in that location. If the phone is lost, revoke the token in Settings → Connections."
+msgstr "任何能打开你手机上该快捷指令的人都可以在该空间中记录读数。如果手机丢失,请在“设置 → 连接”中撤销该令牌。"
+
+msgid "Apps like claude.ai connect over OAuth only to an https address they can reach. Set <0>KEPT_PUBLIC_URL0> to one. Until then, people connect apps with a personal token."
+msgstr "像 claude.ai 这类应用只能通过 OAuth 连接到可公网访问的 https 地址。请将 <0>KEPT_PUBLIC_URL0> 设为该地址。在此之前,成员可使用个人令牌连接应用。"
+
+msgid "Apps using it stop working at once. Changes it made stay, and can still be undone for 7 days."
+msgstr "使用该令牌的应用将立即失效。其已做出的更改会保留,并在 7 天内支持撤销。"
+
+msgid "Available"
+msgstr "可用"
+
+msgid "Callback URL to register at the provider"
+msgstr "需在服务商处登记的回调 URL"
+
+msgid "Change webhook"
+msgstr "更改 Webhook"
+
+msgid "Check a delivery (Node.js)"
+msgstr "校验推送消息 (Node.js)"
+
+msgid "Claude Desktop"
+msgstr "Claude Desktop"
+
+msgid "Configured, not working"
+msgstr "已配置,但无法正常工作"
+
+msgid "Connected apps"
+msgstr "已连接的应用"
+
+msgid "Connected apps (OAuth)"
+msgstr "已连接应用 (OAuth)"
+
+msgid "Connections from other apps"
+msgstr "来自其他应用的连接"
+
+msgid "Connectors (OAuth)"
+msgstr "连接器 (OAuth)"
+
+msgid "Copy address"
+msgstr "复制地址"
+
+msgid "Copy header"
+msgstr "复制表头"
+
+msgid "Copy it now. You won't see it again; rotate it if it's lost."
+msgstr "请立即复制。关闭后将无法再次查看;若遗失请轮换重新生成。"
+
+msgid "Copy it now. You won't see this again: Kept keeps only a fingerprint of it."
+msgstr "请立即复制。关闭后将无法再次查看:Kept 仅保存它的指纹摘要。"
+
+msgid "Copy secret"
+msgstr "复制密钥"
+
+msgid "Couldn't share"
+msgstr "无法分享"
+
+msgid "Delete this webhook?"
+msgstr "删除此 Webhook?"
+
+msgid "Delivered"
+msgstr "已送达"
+
+msgid "Deliveries"
+msgstr "投递记录"
+
+msgid "Deliveries from the last 30 days appear here. Send a test to try it."
+msgstr "最近 30 天的投递记录会显示在这里。发送测试请求即可体验。"
+
+msgid "Deny"
+msgstr "拒绝"
+
+msgid "Different people use these locations"
+msgstr "这些空间由不同人员使用"
+
+msgid "Disconnect {appName}?"
+msgstr "断开 {appName} 的连接?"
+
+msgid "Disconnected by the app"
+msgstr "已被应用断开连接"
+
+msgid "Downloading the local model"
+msgstr "正在下载本地模型"
+
+msgid "Each location's AI"
+msgstr "各空间的 AI"
+
+msgid "Each location's AI provider indexes its things and each search, and that location pays. A location whose provider has no embeddings model searches by words only."
+msgstr "每个空间的 AI 服务商负责为其物品和每次搜索建立索引,费用由该空间承担。若服务商未配置向量模型,则仅支持关键词搜索。"
+
+msgid "Each message carries ids and the names of the fields that changed, never names, places or values. Your server fetches what it needs with its own token."
+msgstr "每条通知仅包含 ID 和发生变更的字段名,绝不包含名称、位置或具体值。你的服务端需使用自身令牌来拉取所需详情。"
+
+msgid "Ended: you left the location"
+msgstr "已结束:你已离开该空间"
+
+msgid "Ended: your role changed"
+msgstr "已终止:你的角色已变更"
+
+msgid "Every token and app"
+msgstr "所有令牌与应用"
+
+msgid "Expires {expires}"
+msgstr "将于 {expires} 过期"
+
+msgid "Failed, trying again"
+msgstr "失败,正在重试"
+
+msgid "Failing"
+msgstr "存在故障"
+
+msgid "Failing since {failingSince}"
+msgstr "自 {failingSince} 起持续失败"
+
+msgid "Find things and add, move or change them. Never delete or see secret fields."
+msgstr "查找物品并添加、移动或修改它们。无法删除物品或查看私密字段。"
+
+msgid "Find things and read what's recorded. No changes, no secret fields."
+msgstr "查找物品并查看已记录的信息。不允许修改,也无法读取私密字段。"
+
+msgid "Fix it, then restart Kept. Everything else works meanwhile."
+msgstr "修复问题后请重启 Kept。在此期间其他功能均可正常使用。"
+
+msgid "Gave up"
+msgstr "已放弃"
+
+msgid "In Settings → Connections, make a token that can read and change, for the car's location only. Copy it."
+msgstr "在「设置 → 连接」中创建一个仅针对该车辆所在空间、且具备读取和修改权限的令牌,然后复制它。"
+
+msgid "In the app, add an MCP server (it may be called a connector or an integration) with this address, and send the token in this header."
+msgstr "在应用中,使用此地址添加一个 MCP 服务器(也可能称为连接器或集成),并在请求头中发送该令牌。"
+
+msgid "In the Shortcuts app, make a new Shortcut. Add <0>Ask for Input0>, set to Number, with the prompt \"Odometer\"."
+msgstr "在“快捷指令”App 中新建一个快捷指令。添加<0>要求输入0>操作,类型设为“数字”,提示文本填“Odometer”。"
+
+msgid "Indexed {indexed} of {total} things"
+msgstr "已索引 {indexed} / {total} 件物品"
+
+msgid "Issuer"
+msgstr "签发方"
+
+msgid "It stops reaching your Kept at once. To use it again, connect it again from the app."
+msgstr "它将立即无法访问你的 Kept。如需再次使用,请在对应应用中重新连接。"
+
+msgid "Join with <0>{oidcName}0>"
+msgstr "通过 <0>{oidcName}0> 加入"
+
+msgid "Kept downloads the model once ({size}) and runs it on this server: no key, no per-call cost. Everything is indexed again with it."
+msgstr "Kept 会一次性下载模型({size})并在本服务器本地运行:无需密钥,无按次调用费用。启用后将使用该模型重新建立全部索引。"
+
+msgid "Kept needs an address that can receive mail for an account."
+msgstr "Kept 需要一个可接收邮件的地址来绑定账号。"
+
+msgid "Kept never matches accounts by their email. If you're new here, open the invite someone sent you and join with <0>{who}0> from there. If you already have an account, sign in another way."
+msgstr "Kept 从不按邮箱自动匹配账号。如果你是新用户,请打开他人发给你的邀请链接,再通过 <0>{who}0> 加入;如果你已有账号,请改用其他方式登录。"
+
+msgid "Kept runs the model on this server: no key, no per-call cost. Everything is indexed again with it."
+msgstr "Kept 会在本服务器本地运行该模型:无需密钥,无按次调用费用。启用后将使用该模型重新建立全部索引。"
+
+msgid "Kept signs every delivery with this secret, so your server can tell it came from Kept."
+msgstr "Kept 会用此密钥对每次推送进行签名,以便你的服务器确认请求来自 Kept。"
+
+msgid "Kept stops sending to it, and its deliveries are forgotten."
+msgstr "Kept 将停止向其发送请求,并清除其投递记录。"
+
+msgid "Keyword only (semantic search is off on this server)"
+msgstr "仅关键词搜索(此服务器未开启语义搜索)"
+
+msgid "Last: {lastWords} {lastAt}"
+msgstr "最近:{lastWords} {lastAt}"
+
+msgid "Last: {lastWords} {lastAt} · HTTP <0>{0}0>"
+msgstr "上次:{lastWords} {lastAt} · HTTP <0>{0}0>"
+
+msgid "Leave empty to keep it until you revoke it."
+msgstr "留空则保持有效,直至你手动撤销。"
+
+msgid "Loading changes"
+msgstr "正在加载变更"
+
+msgid "Loading deliveries"
+msgstr "正在加载推送记录"
+
+msgid "Log your odometer from an iPhone Shortcut"
+msgstr "通过 iPhone 快捷指令记录里程表"
+
+msgid "Made by"
+msgstr "制造商"
+
+msgid "Make a new signing secret?"
+msgstr "生成新的签名密钥?"
+
+msgid "Make it for all of them"
+msgstr "应用到所有物品"
+
+msgid "Make token"
+msgstr "生成令牌"
+
+msgid "matched by meaning"
+msgstr "按语义匹配"
+
+msgid "MCP endpoint"
+msgstr "MCP 端点"
+
+msgid "More than one location"
+msgstr "多个空间"
+
+msgid "Name it after where you'll use it."
+msgstr "按使用位置来命名。"
+
+msgid "Needs an https public URL"
+msgstr "需要 HTTPS 公开地址"
+
+msgid "New secret"
+msgstr "新建密钥"
+
+msgid "New token"
+msgstr "新建令牌"
+
+msgid "New webhook"
+msgstr "新建 Webhook"
+
+msgid "No changes by connections"
+msgstr "外部连接未做任何更改"
+
+msgid "No Kept account uses that sign-in yet"
+msgstr "尚无 Kept 账号使用该登录方式"
+
+msgid "No tokens yet"
+msgstr "暂无令牌"
+
+msgid "No webhooks here"
+msgstr "暂无 Webhook"
+
+msgid "Nothing sent yet"
+msgstr "尚未发送任何内容"
+
+msgid "Off: the person who made it is no longer an admin here."
+msgstr "已关闭:创建该项的人员已不再是此处的管理员。"
+
+msgid "OIDC sign-in is off"
+msgstr "OIDC 登录已关闭"
+
+msgid "One of the provider's addresses isn't https."
+msgstr "该服务商的某个地址未使用 https。"
+
+msgid "Open Connections"
+msgstr "打开「连接」"
+
+msgid "Paste your token in place of the angle brackets and what's between them."
+msgstr "将尖括号及其中的内容替换为你的令牌。"
+
+msgid "People see \"Sign in with <0>{name}0>\""
+msgstr "登录按钮将显示为“使用 <0>{name}0> 登录”"
+
+msgid "Personal tokens"
+msgstr "个人令牌"
+
+msgid "Pick at least one event."
+msgstr "请至少选择一个事件。"
+
+msgid "Pick at least one location."
+msgstr "请至少选择一个空间。"
+
+msgid "Pick only what it needs. You can disconnect it in Settings → Connections."
+msgstr "仅勾选它实际需要的权限。你随时可以在「设置 → 连接」中断开连接。"
+
+msgid "It stays signed in after you sign out of this browser; anything that signs out all your other devices makes it sign in again."
+msgstr "当你退出当前浏览器后,它仍保持登录;但执行“退出所有其他设备”操作会使其重新登录。"
+
+msgid "Read and change"
+msgstr "读取与修改"
+
+msgid "Read only"
+msgstr "只读"
+
+msgid "Read only for you"
+msgstr "你仅有只读权限"
+
+msgid "Read only: you can't change things in <0>{0}0>, so neither can the app."
+msgstr "只读权限:你无法更改 <0>{0}0> 中的内容,因此该应用也无法更改。"
+
+msgid "Read only: you're a viewer in <0>{0}0>, and a token can't do more than you can."
+msgstr "仅限只读:你在 <0>{0}0> 中是查看者,令牌的权限无法超过你自身的权限。"
+
+msgid "Recent changes by connections"
+msgstr "关联应用最近的更改"
+
+msgid "Revoke {name}?"
+msgstr "撤销 {name}?"
+
+msgid "Revoked by an admin"
+msgstr "已被管理员撤销"
+
+msgid "Revoked or expired"
+msgstr "已撤销或已过期"
+
+msgid "Runs on this server; no key; no per-call cost."
+msgstr "直接运行于此服务器;无需密钥,无按次调用费用。"
+
+msgid "Search by address"
+msgstr "按地址搜索"
+
+msgid "Search embeddings"
+msgstr "搜索向量模型"
+
+msgid "Search embeddings updated"
+msgstr "已更新搜索向量索引"
+
+msgid "Search finds things by their words only."
+msgstr "搜索仅按物品文字信息匹配。"
+
+msgid "Search finds things by their words only. Nothing more is sent for indexing."
+msgstr "搜索仅按文字匹配物品,不会再发送任何数据进行索引。"
+
+msgid "Search finds things by their words until then. Indexing carries on after."
+msgstr "在此之前搜索仅按文字匹配,完成后将继续建立索引。"
+
+msgid "Search tokens and apps"
+msgstr "搜索令牌和应用"
+
+msgid "Search webhooks"
+msgstr "搜索 Webhook"
+
+msgid "Semantic search is off on this server · keyword results"
+msgstr "此服务器未开启语义搜索 · 当前显示关键词结果"
+
+msgid "Semantic search is waiting for the AI provider · keyword results"
+msgstr "语义搜索正等待 AI 服务商响应 · 当前显示关键词结果"
+
+msgid "Semantic search paused · keyword results"
+msgstr "语义搜索已暂停 · 当前显示关键词结果"
+
+msgid "Semantic search paused until {until} · keyword results"
+msgstr "语义搜索已暂停至 {until} · 当前显示关键词结果"
+
+msgid "Send a test"
+msgstr "发送测试"
+
+msgid "Send to"
+msgstr "发送至"
+
+msgid "Send to {0}"
+msgstr "发送到 {0}"
+
+msgid "Server address"
+msgstr "服务器地址"
+
+msgid "Set <0>KEPT_OIDC_ISSUER0>, <1>KEPT_OIDC_CLIENT_ID1> and <2>KEPT_OIDC_CLIENT_SECRET2>, then restart Kept."
+msgstr "请设置 <0>KEPT_OIDC_ISSUER0>、<1>KEPT_OIDC_CLIENT_ID1> 和 <2>KEPT_OIDC_CLIENT_SECRET2>,然后重启 Kept。"
+
+msgid "Set Request Body to JSON with two text fields: <0>value0>, the number you typed, and <1>takenAt1>, the Current Date formatted as ISO 8601 with the time."
+msgstr "将请求体 (Request Body) 设为包含两个文本字段的 JSON:<0>value0> 为你输入的数值,<1>takenAt1> 为含时间的 ISO 8601 格式当前日期。"
+
+msgid "Show the recipe"
+msgstr "查看制作步骤"
+
+msgid "Sign in with <0>{name}0>"
+msgstr "使用 <0>{name}0> 登录"
+
+msgid "Sign-in with OIDC"
+msgstr "使用 OIDC 登录"
+
+msgid "Signing in this way reaches only an account already linked to it, or someone invited here. Kept never joins accounts because their emails match."
+msgstr "此登录方式仅适用于已绑定该方式的账号或受邀用户。Kept 不会因为邮箱相同而自动合并账号。"
+
+msgid "Signing in with <0>{who}0> didn't work"
+msgstr "使用 <0>{who}0> 登录失败"
+
+msgid "Signing secret"
+msgstr "签名密钥"
+
+msgid "Start connecting again from the app."
+msgstr "请从应用中重新开始连接。"
+
+msgid "Tap the Shortcut at the pump or in the car park, type the odometer, and the reading is in Kept, with undo, as if you'd logged it here."
+msgstr "在加油站或停车场轻点快捷指令并输入里程数,读数就会直接记入 Kept,效果与在应用内记录一致(同样支持撤销)。"
+
+msgid "Tell your own server when things change here."
+msgstr "当这里发生变动时通知你自己的服务器。"
+
+msgid "Test sent: your server answered {code}"
+msgstr "测试已发送:你的服务器返回状态码 {code}"
+
+msgid "That address is on a private network, which this server doesn't allow."
+msgstr "该地址位于私有网络中,此服务器不允许访问。"
+
+msgid "That email address can't be used"
+msgstr "无法使用该邮箱地址"
+
+msgid "That's the name the app gives itself. Kept can't confirm who made it."
+msgstr "这是应用自报的名称。Kept 无法核实其开发者身份。"
+
+msgid "The app could move what it finds in one into another, so people in one could see what came from the other. Connect it to one location unless you mean that."
+msgstr "该应用可能会将一个空间中查找到的内容移入另一个空间,使两个空间的成员互相看到彼此的数据。除非确有此意,否则请仅连接到一个空间。"
+
+msgid "The app reads all of them together, and could repeat what it reads in one to someone who uses another. Connect it to one location unless you mean that."
+msgstr "该应用会同时读取所有已连接空间的数据,并可能向其中一个空间的成员提及另一空间的内容。除非确有此意,否则请仅连接到一个空间。"
+
+msgid "The current secret stops working at once. Deliveries fail to verify until your server has the new one."
+msgstr "当前密钥将立即失效。在你的服务器更新为新密钥之前,推送校验将会失败。"
+
+msgid "The email addresses don't match"
+msgstr "两次输入的邮箱地址不一致"
+
+msgid "The email on your <0>{who}0> account isn't the one this invite or account is for."
+msgstr "你的 <0>{who}0> 账号关联的邮箱与此邀请或账号不匹配。"
+
+msgid "The local model isn't installed on this server, so it can't be chosen."
+msgstr "此服务器尚未安装本地模型,因此无法选择。"
+
+msgid "The old secret stopped working. Put this one on your server; every delivery from now on is signed with it."
+msgstr "旧密钥已失效。请将此新密钥配置到你的服务器上;此后每次推送都将使用它进行签名。"
+
+msgid "The provider couldn't be reached when Kept started."
+msgstr "Kept 启动时无法连接到该服务商。"
+
+msgid "The provider says it's a different issuer from KEPT_OIDC_ISSUER."
+msgstr "服务商返回的签发者 (Issuer) 与 KEPT_OIDC_ISSUER 不一致。"
+
+msgid "The provider's address is on a private network, which this server doesn't allow."
+msgstr "该服务商的地址位于内网,当前服务器不允许访问。"
+
+msgid "The provider's discovery document didn't load."
+msgstr "未能加载服务商的发现文档。"
+
+msgid "The token lives in the Shortcut"
+msgstr "令牌保存在快捷指令中"
+
+msgid "There's no account for you here yet"
+msgstr "你在这里还没有账号"
+
+msgid "Things indexed for search"
+msgstr "已建立搜索索引的物品"
+
+msgid "This Kept lets people in by invite. Ask someone who uses it to invite you, then join from the invite link."
+msgstr "此 Kept 实例仅限受邀加入。请让现有用户向你发送邀请,然后通过邀请链接加入。"
+
+msgid "This request isn't valid any more"
+msgstr "此请求已失效"
+
+msgid "This server: a {size} download, once. Runs here; no key; no per-call cost."
+msgstr "本地服务器:需一次性下载 {size} 模型文件。完全本地运行,无需密钥,无按次调用费用。"
+
+msgid "Tokens and connected apps"
+msgstr "令牌与已连接应用"
+
+msgid "Tokens and connected apps let AI apps like Claude, and your own scripts, find and add your things. Each is limited to the locations you choose, and every change it makes is listed below with undo."
+msgstr "借助令牌与已连接应用,Claude 等 AI 应用及你自己的脚本可以查找并添加物品。每项授权仅限于你选定的空间,且每次变更都会列在下方并支持撤销。"
+
+msgid "Try again, or sign in another way. The reason it gave: <0>{code}0>"
+msgstr "请重试,或换一种方式登录。返回原因:<0>{code}0>"
+
+msgid "Trying again {next}"
+msgstr "将于 {next} 重试"
+
+msgid "Turn semantic search off?"
+msgstr "关闭语义搜索?"
+
+msgid "Turned off by an admin."
+msgstr "已被管理员关闭。"
+
+msgid "Under Headers, add these two:"
+msgstr "在 Headers(请求头)下,添加以下两项:"
+
+msgid "Undo for 7 days"
+msgstr "7 天内可撤销"
+
+msgid "Use a local model for search?"
+msgstr "使用本地模型进行搜索?"
+
+msgid "Use the local model"
+msgstr "使用本地模型"
+
+msgid "Waiting to send"
+msgstr "等待发送"
+
+msgid "Webhook deleted"
+msgstr "Webhook 已删除"
+
+msgid "Webhook off"
+msgstr "Webhook 已关闭"
+
+msgid "Webhook on"
+msgstr "Webhook 已开启"
+
+msgid "Webhook saved"
+msgstr "Webhook 已保存"
+
+msgid "What it can do"
+msgstr "功能范围"
+
+msgid "When an app changes something with one of your tokens, it's listed here."
+msgstr "当应用使用你的某个令牌修改数据时,相关记录会显示在这里。"
+
+msgid "Where"
+msgstr "位置"
+
+msgid "Where meaning comes from"
+msgstr "语义来源"
+
+msgid "Where you'll use it: \"Claude Desktop, my laptop\", \"Shortcuts on my iPhone\"."
+msgstr "备注用途,例如「笔记本上的 Claude Desktop」、「iPhone 上的快捷指令」。"
+
+msgid "Working"
+msgstr "正常使用"
+
+msgid "Your email isn't confirmed"
+msgstr "你的邮箱尚未验证"
+
+msgid "Your new token"
+msgstr "你的新令牌"
+
+msgid "Your server didn't answer"
+msgstr "服务器未响应"
+
+msgid "Your server's address. Kept sends a signed POST there."
+msgstr "你的服务器地址。Kept 会向该地址发送签名后的 POST 请求。"
+
+msgid "Delete this thread"
+msgstr "删除此对话"
+
+msgid "Earlier this week"
+msgstr "本周早些时候"
+
+msgid "Earlier"
+msgstr "更早"
+
+msgid "Last used"
+msgstr "上次使用"
+
+msgid "by when"
+msgstr "截止时间"
+
+msgid "ungrouped"
+msgstr "未分组"
+
+msgid "Ask a question"
+msgstr "提问"
+
+msgid "Your threads"
+msgstr "你的对话"
+
+msgid "Search your threads"
+msgstr "搜索你的对话"
+
+msgid "Search your questions and answers"
+msgstr "搜索你的提问与回答"
+
+msgid "Dictation (the mic)"
+msgstr "语音输入(麦克风)"
+
+msgid "Ask the assistant about “{0}”"
+msgstr "向 AI 助手询问关于“{0}”"
+
+msgid "Kept can't use the microphone"
+msgstr "Kept 无法使用麦克风"
+
+msgid "Allow it in the browser's settings, or type instead."
+msgstr "请在浏览器设置中允许权限,或改为手动输入。"
+
+msgid "Stop dictation"
+msgstr "停止语音输入"
+
+msgid "Dictate"
+msgstr "语音听写"
+
+msgid "Things in this answer"
+msgstr "此回答涉及的物品"
+
+msgid "Removed: you no longer have access to this"
+msgstr "已移除:你已无权访问此内容"
+
+msgid "Looking…"
+msgstr "正在查找…"
+
+msgid "Checked your locations"
+msgstr "已检查你的空间"
+
+msgid "Checked what's due in {where}"
+msgstr "已查看 {where} 的到期事项"
+
+msgid "Checked what's due"
+msgstr "已检查到期事项"
+
+msgid "Looked through the paperwork in {where}"
+msgstr "已查阅 {where} 中的相关文档"
+
+msgid "Looked through the paperwork"
+msgstr "已查阅文档资料"
+
+msgid "Looked in {where}"
+msgstr "已检查 {where}"
+
+msgid "Looked it up"
+msgstr "已查询"
+
+msgid "Assistant, needs a connection"
+msgstr "AI 助手需要网络连接"
+
+msgid "Send"
+msgstr "发送"
+
+msgid "Listening… tap the mic again to stop."
+msgstr "正在聆听… 再次轻点麦克风即可停止。"
+
+msgid "Seen it"
+msgstr "知道了"
+
+msgid "New place"
+msgstr "新建位置"
+
+msgid "Add a photo or document"
+msgstr "添加照片或文档"
+
+msgid "Log reading"
+msgstr "记录读数"
+
+msgid "Return"
+msgstr "归还"
+
+msgid "Borrow"
+msgstr "借入"
+
+msgid "Mark done"
+msgstr "标记为完成"
+
+msgid "Add warranty"
+msgstr "添加保修"
+
+msgid "Open claim"
+msgstr "提交理赔"
+
+msgid "Update claim"
+msgstr "更新理赔"
+
+msgid "Log service"
+msgstr "记录维护"
+
+msgid "Log fill-up"
+msgstr "记录加油/充电"
+
+msgid "Adjust stock"
+msgstr "调整库存"
+
+msgid "One up"
+msgstr "上一级"
+
+msgid "One down"
+msgstr "已完成一项"
+
+msgid "Field"
+msgstr "字段"
+
+msgid "Ends"
+msgstr "结束时间"
+
+msgid "Done by"
+msgstr "执行人"
+
+msgid "Work"
+msgstr "办公"
+
+msgid "Change in stock"
+msgstr "库存变更"
+
+msgid "Nothing"
+msgstr "无"
+
+msgid "{count} ×"
+msgstr "{count} ×"
+
+msgid "{count} of {total} ×"
+msgstr "{count} / {total} ×"
+
+msgid "Something Kept can't name"
+msgstr "Kept 无法识别名称的物品"
+
+msgid "Include: {0} {1}"
+msgstr "包含:{0} {1}"
+
+msgid "{0}× {1}"
+msgstr "{0} × {1}"
+
+msgid "Moved {0} to {where}"
+msgstr "已将 {0} 移至 {where}"
+
+msgid "Moved {0}"
+msgstr "已移动 {0}"
+
+msgid "{0, plural, one {Saved # change} other {Saved # changes}}"
+msgstr "{0, plural, one {已保存 # 处更改} other {已保存 # 处更改}}"
+
+msgid "Some changes couldn't be saved. Ask again."
+msgstr "部分更改未能保存,请重新尝试。"
+
+msgid "Expired · ask again"
+msgstr "已过期 · 请重新申请"
+
+msgid "Nothing was changed"
+msgstr "未作任何更改"
+
+msgid "Changed since you asked"
+msgstr "自你提问后已有变更"
+
+msgid "Undo it from Activity for 7 days"
+msgstr "7 天内可在“活动”中撤销"
+
+msgid "Not saved"
+msgstr "未保存"
+
+msgid "Ask again to try once more"
+msgstr "请再次提问重试"
+
+msgid "{n, plural, one {Confirm # change} other {Confirm # changes}}"
+msgstr "{n, plural, one {确认 # 处更改} other {确认 # 处更改}}"
+
+msgid "Only ticked rows are saved"
+msgstr "仅保存已勾选的行"
+
+msgid "Changes for you to confirm, drawn by Kept"
+msgstr "由 Kept 整理、待你确认的变更"
+
+msgid "Time left to confirm"
+msgstr "剩余确认时间"
+
+msgid "{count, plural, one {Confirm #} other {Confirm #}}"
+msgstr "{count, plural, one {确认 # 项} other {确认 # 项}}"
+
+msgid "Ask again"
+msgstr "重新询问"
+
+msgid "<0>{0}0> changed it since"
+msgstr "<0>{0}0> 在此之后修改过"
+
+msgid "When you asked"
+msgstr "查询时间"
+
+msgid "Now"
+msgstr "现在"
+
+msgid "Page context:"
+msgstr "页面上下文:"
+
+msgid "“{0}”"
+msgstr "“{0}”"
+
+msgid "Remove page context"
+msgstr "移除页面上下文"
+
+msgid "Connect AI in Settings"
+msgstr "在设置中连接 AI"
+
+msgid "AI isn't set up here"
+msgstr "此处尚未配置 AI"
+
+msgid "The assistant is still answering here. Wait for it, or cancel it."
+msgstr "AI 助手仍在回复中。请稍候,或取消本次回答。"
+
+msgid "Enter to send · this thread is private to you"
+msgstr "按 Enter 发送 · 此对话仅自己可见"
+
+msgid "This thread is private to you"
+msgstr "此对话仅你本人可见"
+
+msgid "Viewers can ask; changes need an admin"
+msgstr "查看者可提问;修改需管理员权限"
+
+msgid "Ask where something is or what's due, or ask for a change. Nothing changes until you confirm the card Kept shows you."
+msgstr "询问物品位置或即将到期的事项,或请求进行修改。在你确认 Kept 展示的操作卡片之前,任何内容都不会更改。"
+
+msgid "Say or type a list, like “in the garage I have a drill, a ladder and two paint cans”, and add them all with one Confirm."
+msgstr "语音或输入一段清单,例如「车库里有一把电钻、一架梯子和两桶油漆」,确认一次即可全部添加。"
+
+msgid "Back to the conversation"
+msgstr "返回对话"
+
+msgid "Threads"
+msgstr "对话列表"
+
+msgid "New thread"
+msgstr "新建对话"
+
+msgid "Close panel"
+msgstr "关闭面板"
+
+msgid "About"
+msgstr "关于"
+
+msgid "Thinking…"
+msgstr "正在思考…"
+
+msgid "Waiting for <0>{provider}0> · about {secs} s"
+msgstr "正在等待 <0>{provider}0> · 约 {secs} 秒"
+
+msgid "Waiting for <0>{provider}0>"
+msgstr "正在等待 <0>{provider}0>"
+
+msgid "The assistant couldn't finish this answer. Ask again."
+msgstr "AI 助手未能完成此回答,请重试。"
+
+msgid "Thread deleted"
+msgstr "对话已删除"
+
+msgid "Delete “{0}”?"
+msgstr "删除“{0}”?"
+
+msgid "It's deleted now, for good. Nothing else changes."
+msgstr "现已永久删除,其他内容不受影响。"
+
+msgid "Delete “{0}”"
+msgstr "删除「{0}」"
+
+msgid "Private to you. Deleted after {days} days without a new question."
+msgstr "仅你可见。若 {days} 天内无新提问将自动删除。"
+
+msgid "Loading your threads"
+msgstr "正在加载对话"
+
+msgid "Nothing matches. Try fewer words."
+msgstr "没有匹配项,请尝试减少关键词。"
+
+msgid "No threads yet"
+msgstr "暂无对话"
+
+msgid "Your questions and their answers are kept here, private to you."
+msgstr "你的提问与回答都保存在这里,仅你可见。"
+
+msgid "All threads"
+msgstr "全部对话"
+
+msgid "Backups"
+msgstr "备份"
+
+msgctxt "disk"
+msgid "Backups"
+msgstr "备份"
+
+msgid "Lock Kept on this device"
+msgstr "在此设备上锁定 Kept"
+
+msgid "Issued on"
+msgstr "签发日期"
+
+msgid "Missed a fill-up before it"
+msgstr "此前漏记了一次加油"
+
+msgid "Fuel changed"
+msgstr "燃料信息已更改"
+
+msgid "Fuel deleted"
+msgstr "已删除加油记录"
+
+msgid "Starter schedules added"
+msgstr "已添加初始维护计划"
+
+msgid "{nudgeDays, plural, one {A fresh one keeps ~{next} honest; Kept nudges you at # day.} other {A fresh one keeps ~{next} honest; Kept nudges you at # days.}}"
+msgstr "{nudgeDays, plural, one {更新读数可让 ~{next} 保持准确;满 # 天时 Kept 会提醒你。} other {更新读数可让 ~{next} 保持准确;满 # 天时 Kept 会提醒你。}}"
+
+msgid "{nudgeDays, plural, one {Kept nudges you at # day.} other {Kept nudges you at # days.}}"
+msgstr "{nudgeDays, plural, one {Kept 会在第 # 天提醒你。} other {Kept 会在第 # 天提醒你。}}"
+
+msgid "A location's webhook keeps failing"
+msgstr "某个空间的 Webhook 持续失败"
+
+msgid "No backup for more than 36 hours"
+msgstr "超过 36 小时未进行备份"
+
+msgid "A disk is nearly full"
+msgstr "磁盘空间即将耗尽"
+
+msgid "Versioning is off on the file bucket"
+msgstr "文件存储桶未开启版本控制"
+
+msgid "Time for a restore drill"
+msgstr "该进行恢复演练了"
+
+msgid "The latest backup looks too small"
+msgstr "最新备份文件似乎过小"
+
+msgid "No backup has finished yet. The next good run resolves this alert."
+msgstr "尚未完成过备份。下次备份成功后将自动解除此告警。"
+
+msgid "The backup disk is {used}% full."
+msgstr "备份磁盘已使用 {used}%。"
+
+msgid "The data disk is {used}% full."
+msgstr "数据磁盘已使用 {used}%。"
+
+msgid "Last restore drill {last}. A new drill resolves this alert."
+msgstr "上次恢复演练为 {last}。完成一次新演练即可解除此提醒。"
+
+msgid "No restore drill yet. A drill resolves this alert."
+msgstr "尚未进行恢复演练。完成一次恢复演练即可解除此告警。"
+
+msgid "Download recovery kit"
+msgstr "下载恢复工具包"
+
+msgid "Download the recovery kit"
+msgstr "下载恢复工具包"
+
+msgid "Everything needed to bring Kept back on a new server: the secret keys, the backup's location, its password and storage keys, and the restore steps."
+msgstr "在新服务器上恢复 Kept 所需的全部资料:加密密钥、备份位置、密码与存储密钥,以及恢复步骤。"
+
+msgid "Keep it off this server"
+msgstr "不要保存在此服务器上"
+
+msgid "Print it or store it in a password manager. Anyone with it can read your backups."
+msgstr "请打印或妥善保存在密码管理器中。任何拿到它的人都可以读取你的备份。"
+
+msgid "Format"
+msgstr "格式"
+
+msgid "Text file"
+msgstr "文本文件"
+
+msgid "Printable page"
+msgstr "可打印页面"
+
+msgid "Recovery kit downloaded. Keep it off this server."
+msgstr "恢复工具包已下载。请勿将其保存在此服务器上。"
+
+msgid "Sign in again"
+msgstr "重新登录"
+
+msgid "Your account has no password, and you signed in over ten minutes ago. Sign in again, then come back here."
+msgstr "你的账号没有设置密码,且距离上次登录已超过十分钟。请重新登录后再回到此页面。"
+
+msgid "No password on your account? Leave this empty: a sign-in in the last ten minutes is enough."
+msgstr "账号没有设置密码?此处可留空:近十分钟内的登录即可通过验证。"
+
+msgid "The recovery kit changed since you downloaded it"
+msgstr "自你上次下载后,恢复工具包已发生变化"
+
+msgid "The key was rotated or the backup settings changed, so the kit you have can't restore everything. Download it again and replace the old one."
+msgstr "密钥已轮换或备份设置已更改,你当前的恢复工具包无法恢复全部内容。请重新下载并替换旧文件。"
+
+msgid "Keep the recovery kit somewhere else"
+msgstr "请将恢复工具包存放在其他位置"
+
+msgid "Kept encrypts secret fields, AI keys and the backup password with KEPT_SECRET_KEY. If this server and its key are lost together, a backup still restores your things, but not those. Download the recovery kit (or print it with <0>kept admin recovery-kit0>) and keep it away from this server. Kept asks for this before the first secret, AI key or backup."
+msgstr "Kept 使用 KEPT_SECRET_KEY 加密私密字段、AI 密钥和备份密码。如果服务器与密钥同时丢失,备份仍可恢复你的物品数据,但无法恢复上述加密内容。请下载恢复工具包(或通过 <0>kept admin recovery-kit0> 打印),并存放在服务器之外的安全位置。在首次配置私密字段、AI 密钥或备份前,Kept 会要求完成此步骤。"
+
+msgid "Changed since you downloaded it"
+msgstr "自你下载后已有变更"
+
+msgid "Downloaded {day}"
+msgstr "下载于 {day}"
+
+msgid "Download again"
+msgstr "重新下载"
+
+msgid "{0} is kept offline on this device"
+msgstr "{0} 已离线保存在此设备上"
+
+msgid "{0} of {1} on this device"
+msgstr "此设备上已缓存 {0} / {1}"
+
+msgid "{0} of {dots} digits"
+msgstr "已输入 {0} / {dots} 位"
+
+msgid "{keptCount, plural, one {The # location kept offline is removed from this device too.} other {The # locations kept offline are removed from this device too.}}"
+msgstr "{keptCount, plural, one {保留离线的 # 个空间也会从此设备中移除。} other {保留离线的 # 个空间也会从此设备中移除。}}"
+
+msgid "{left, plural, one {Wrong PIN. # try left before this device’s copy is removed.} other {Wrong PIN. # tries left before this device’s copy is removed.}}"
+msgstr "{left, plural, one {PIN 码错误。还剩 # 次机会,失败后将清除此设备上的离线副本。} other {PIN 码错误。还剩 # 次机会,失败后将清除此设备上的离线副本。}}"
+
+msgid "{0, plural, one {# document is too large to keep offline:} other {# documents are too large to keep offline:}}"
+msgstr "{0, plural, one {# 份文档过大,无法离线保留:} other {# 份文档过大,无法离线保留:}}"
+
+msgid "{0, plural, one {# document is too large to keep offline.} other {# documents are too large to keep offline.}}"
+msgstr "{0, plural, one {有 # 份文档过大,无法离线保存。} other {有 # 份文档过大,无法离线保存。}}"
+
+msgid "{0, plural, one {locks after # minute away} other {locks after # minutes away}}"
+msgstr "{0, plural, one {离开 # 分钟后自动锁定} other {离开 # 分钟后自动锁定}}"
+
+msgid "About {0} to download"
+msgstr "约需下载 {0}"
+
+msgid "App lock"
+msgstr "应用锁"
+
+msgid "Ask for a PIN when Kept opens and after five minutes away. Keeping a location offline needs it."
+msgstr "打开 Kept 时以及离开五分钟后要求输入 PIN 码。离线保留空间需要开启此项。"
+
+msgid "Change PIN"
+msgstr "更改 PIN 码"
+
+msgid "Choose a PIN of 6 to 12 digits."
+msgstr "请设置 6 至 12 位数字的 PIN 码。"
+
+msgid "Current value"
+msgstr "当前价值"
+
+msgid "Didn’t finish. Update to try again."
+msgstr "未能完成。请更新后重试。"
+
+msgid "Downloading {0} of {1}"
+msgstr "正在下载第 {0} / {1} 项"
+
+msgid "Enter PIN"
+msgstr "输入 PIN 码"
+
+msgid "Enter your current PIN."
+msgstr "请输入你当前的 PIN 码。"
+
+msgid "Enter your PIN"
+msgstr "输入你的 PIN 码"
+
+msgid "Enter your PIN to open the prices and documents kept on this device."
+msgstr "输入你的 PIN 码以解锁保存在此设备上的价格与文档。"
+
+msgid "Face ID"
+msgstr "面容 ID"
+
+msgid "Face ID or fingerprint can unlock Kept now"
+msgstr "现在可以使用面容 ID 或指纹解锁 Kept"
+
+msgid "Face ID or fingerprint didn’t work. Enter your PIN."
+msgstr "面容 ID 或指纹识别失败,请输入你的 PIN 码。"
+
+msgid "Face ID or fingerprint wasn’t set up"
+msgstr "尚未设置面容 ID 或指纹"
+
+msgid "Forgot it? Sign out and sign in again."
+msgstr "忘记了?请退出登录后重新登录。"
+
+msgid "If this phone is lost"
+msgstr "如果这台手机丢失"
+
+msgid "Keep {0} available offline"
+msgstr "离线保留 {0}"
+
+msgid "Keep {0} available offline?"
+msgstr "要让 {0} 离线可用吗?"
+
+msgid "Keep available offline"
+msgstr "设为离线可用"
+
+msgid "Keep offline"
+msgstr "离线保存"
+
+msgid "Keeping {0} offline didn’t finish"
+msgstr "离线缓存 {0} 未完成"
+
+msgid "Kept app lock"
+msgstr "Kept 应用锁"
+
+msgid "Kept locks on this device now"
+msgstr "Kept 现已在此设备上锁定"
+
+msgid "Kept offline is locked behind your PIN."
+msgstr "Kept 离线数据已受你的 PIN 码锁定保护。"
+
+msgid "Kept on this device"
+msgstr "保存在此设备上"
+
+msgid "Lock Kept with a PIN, and keep a location available offline."
+msgstr "使用 PIN 码锁定 Kept,并将某个空间缓存至本地以供离线查看。"
+
+msgid "Not available in this browser"
+msgstr "在此浏览器中不可用"
+
+msgid "Now turn on Face ID or fingerprint again"
+msgstr "请重新开启面容 ID 或指纹解锁"
+
+msgid "On this phone Face ID or fingerprint opens Kept, but prices and documents kept offline still ask for the PIN."
+msgstr "在此手机上可通过面容 ID 或指纹打开 Kept,但查看离线保存的价格和文档仍需输入 PIN 码。"
+
+msgid "PIN"
+msgstr "PIN 码"
+
+msgid "PIN changed"
+msgstr "PIN 码已更改"
+
+msgid "PIN set"
+msgstr "已设置 PIN 码"
+
+msgid "Sign out and sign in again?"
+msgstr "退出并重新登录?"
+
+msgid "That didn’t work. Try again."
+msgstr "操作未成功,请重试。"
+
+msgid "That is more than this device can keep offline."
+msgstr "这超出了此设备可离线保存的容量上限。"
+
+msgid "The app lock needs storage this browser doesn’t give Kept."
+msgstr "应用锁所需的本地存储权限未获当前浏览器允许。"
+
+msgid "The PIN keeps out someone holding this phone. Forgot it? Sign out and sign in again."
+msgstr "PIN 码可防止他人拿到此手机后直接查看。忘记 PIN 码?请退出登录后重新登录。"
+
+msgid "The PINs don’t match. Type the new PIN again."
+msgstr "两次输入的 PIN 码不一致,请重新输入新 PIN 码。"
+
+msgid "This device’s copy and what you kept offline are removed. Captures you haven’t sent yet stay on this phone and go once you sign in again."
+msgstr "此设备上的本地副本和离线缓存内容将被清除。尚未发送的采集内容仍保留在这台手机上,重新登录后会自动上传。"
+
+msgid "This document isn’t on this device"
+msgstr "此文档不在当前设备上"
+
+msgid "Too large to keep offline ({0})"
+msgstr "体积过大,无法离线保存({0})"
+
+msgid "Turn off one of these first: {list}"
+msgstr "请先关闭以下其中一项:{list}"
+
+msgid "Turn on the app lock first: what you keep offline is locked behind it."
+msgstr "请先开启应用锁:离线保存的内容受应用锁保护。"
+
+msgid "Turn the app lock off"
+msgstr "关闭应用锁"
+
+msgid "Type it again."
+msgstr "请再输入一次。"
+
+msgid "updated {0}"
+msgstr "更新于 {0}"
+
+msgid "Whoever unlocks Kept on this phone sees prices and documents for this location."
+msgstr "任何在此手机上解锁 Kept 的人都能查看该空间的价格和文档。"
+
+msgid "Whoever unlocks Kept on this phone sees prices and documents for this location. About {0} to download."
+msgstr "任何在此手机上解锁 Kept 的人都能看到该空间的价格与文档。约需下载 {0}。"
+
+msgid "Whoever unlocks Kept sees prices and documents for these locations. The PIN keeps out someone holding the phone, not someone who has copied the browser’s storage."
+msgstr "任何解锁 Kept 的人都能看到这些空间的价格和文档。PIN 码仅可防备拿到你手机的人,无法防备复制了浏览器存储数据的人。"
+
+msgid "Wrong PIN."
+msgstr "PIN 码错误。"
+
+msgid "{added} added"
+msgstr "已添加 {added}"
+
+msgid "{free} free"
+msgstr "可用 {free}"
+
+msgid "{n} in the last day"
+msgstr "过去 24 小时内共 {n} 次"
+
+msgid "{pct}% full"
+msgstr "已满 {pct}%"
+
+msgid "{repo} in the repository"
+msgstr "存储库中的 {repo}"
+
+msgid "{snapshots} snapshots"
+msgstr "{snapshots} 份快照"
+
+msgid "A backup is already running. Wait for it to finish."
+msgstr "已有备份正在运行,请等待其完成。"
+
+msgid "A backup is only as good as the keys that open it. Download the recovery kit and keep it off this server, then save again."
+msgstr "备份的安全性取决于解开它的密钥。请下载恢复工具包并妥善保存在服务器之外,然后再重新保存。"
+
+msgid "A folder inside the bucket, ending in a slash."
+msgstr "存储桶内的文件夹路径,以斜杠结尾。"
+
+msgid "Absolute, or relative to the user's home folder."
+msgstr "绝对路径,或相对于用户主目录的路径。"
+
+msgid "Access key ID"
+msgstr "Access Key ID"
+
+msgid "An absolute path as the server sees it: another disk, or a NAS mount. Not the disk Kept's data is on."
+msgstr "服务器视角下的绝对路径:例如另一块磁盘或 NAS 挂载点,切勿使用 Kept 数据所在的磁盘。"
+
+msgid "An OpenSSH private key. It replaces the saved key when you save."
+msgstr "OpenSSH 私钥。保存后将替换当前已存的密钥。"
+
+msgid "Another run holds the repository. Try again when it finishes."
+msgstr "另一个任务正在占用仓库,请待其完成后重试。"
+
+msgid "At least 12 characters. Without it nobody can read the backups, Kept included."
+msgstr "至少 12 个字符。没有此密码,包括 Kept 在内的任何人都无法读取备份。"
+
+msgid "Backup password"
+msgstr "备份密码"
+
+msgid "Backup runs"
+msgstr "备份运行情况"
+
+msgid "Backup settings and the recovery kit can only be changed over HTTPS."
+msgstr "备份设置和恢复工具包只能通过 HTTPS 修改。"
+
+msgid "Backup settings saved"
+msgstr "备份设置已保存"
+
+msgid "Backup started. It shows in the runs below."
+msgstr "备份已启动,运行状态将显示在下方列表中。"
+
+msgid "Backups are on the same disk as your data"
+msgstr "备份与你的数据存储在同一块磁盘上"
+
+msgid "Backups need a password: no password, no backup."
+msgstr "备份必须设置密码:无密码则无法备份。"
+
+msgid "Backups should run every night. Check the runs in Backups, and that Kept's worker is running."
+msgstr "备份应每晚自动运行。请检查“备份”中的执行记录,并确认 Kept 的后台任务进程正在运行。"
+
+msgid "Before upgrade"
+msgstr "升级前"
+
+msgid "Bucket"
+msgstr "存储桶"
+
+msgid "Can't check this build"
+msgstr "无法检查此构建版本"
+
+msgid "Change the locked settings in the server's configuration (<0>{0}0>) and restart Kept."
+msgstr "请在服务器配置文件 (<0>{0}0>) 中修改已锁定的设置,然后重启 Kept。"
+
+msgid "Check for new versions"
+msgstr "检查新版本"
+
+msgid "Check this."
+msgstr "请检查此项。"
+
+msgid "Checked {checkedAt}"
+msgstr "检查于 {checkedAt}"
+
+msgid "Checked for new versions"
+msgstr "已检查新版本"
+
+msgid "Choose where backups go and a password. Kept then backs up the database, the files and a readable copy of every location every night, encrypted."
+msgstr "选择备份保存位置和加密密码。此后 Kept 每晚都会加密备份数据库、附件文件以及每个空间的可读副本。"
+
+msgid "Choose where backups go and set their password first."
+msgstr "请先选择备份位置并设置备份密码。"
+
+msgid "Configured"
+msgstr "已配置"
+
+msgid "Couldn't reach GitHub"
+msgstr "无法连接到 GitHub"
+
+msgid "Couldn't reach it"
+msgstr "无法连接"
+
+msgid "Couldn't reach the backup storage. The next run tries again tonight."
+msgstr "无法连接备份存储,今晚下次运行时将重试。"
+
+msgid "Couldn't read the answer"
+msgstr "无法读取回复"
+
+msgid "Create one now, or the first backup creates it."
+msgstr "立即创建一个,或在首次备份时自动创建。"
+
+msgid "Create the repository"
+msgstr "创建存储库"
+
+msgid "Daily"
+msgstr "每天"
+
+msgid "Data"
+msgstr "数据"
+
+msgid "Database at migration <0>{migration}0>"
+msgstr "数据库当前迁移版本:<0>{migration}0>"
+
+msgid "Directory"
+msgstr "目录"
+
+msgid "Disk"
+msgstr "磁盘"
+
+msgid "Download the recovery kit first."
+msgstr "请先下载恢复套件。"
+
+msgid "Each night's backup, and every Run now, shows here."
+msgstr "每晚自动备份以及每次立即备份的记录都会显示在这里。"
+
+msgid "Empty for AWS. B2 and R2 through their S3 endpoints."
+msgstr "AWS 请留空。B2 和 R2 请填写各自的 S3 端点。"
+
+msgid "Endpoint"
+msgstr "端点"
+
+msgid "Every night at (UTC)"
+msgstr "每晚执行时间 (UTC)"
+
+msgid "Every night at <0>{time}0> UTC, keeping {daily} daily, {weekly} weekly and {monthly} monthly snapshots."
+msgstr "每晚 UTC <0>{time}0> 执行,保留 {daily} 份每日、{weekly} 份每周和 {monthly} 份每月快照。"
+
+msgid "Every week, Kept checks that every snapshot can be read."
+msgstr "每周,Kept 会校验每个备份快照是否均可正常读取。"
+
+msgid "File bucket versioning"
+msgstr "文件存储桶版本控制"
+
+msgid "Folder"
+msgstr "文件夹"
+
+msgid "Folder on the server"
+msgstr "服务器上的文件夹"
+
+msgid "From the repository, {cached}"
+msgstr "来自存储库,{cached}"
+
+msgid "GitHub shows no published release for this server's source repository. It may be private, or have none yet."
+msgstr "GitHub 上未找到此服务器源码仓库的已发布版本。该仓库可能为私有,或尚未发布正式版本。"
+
+msgid "GitHub's answer wasn't what Kept expected. Kept asks again tomorrow."
+msgstr "GitHub 返回了意外响应,Kept 明天会再次检查。"
+
+msgid "GitHub's limit reached"
+msgstr "已达到 GitHub 接口上限"
+
+msgid "Host key"
+msgstr "主机密钥"
+
+msgid "Keep the saved one"
+msgstr "保留已保存的"
+
+msgid "Kept {v} is available"
+msgstr "Kept {v} 现已可用"
+
+msgid "Kept <0>{version}0> is available"
+msgstr "Kept <0>{version}0> 已发布"
+
+msgid "Kept allows one release back. Upgrade again when the problem that made you roll back is fixed."
+msgstr "Kept 仅允许回退一个版本。导致回退的问题修复后,请再次升级。"
+
+msgid "Kept checks it with each backup."
+msgstr "Kept 每次备份时都会校验密码。"
+
+msgid "Kept doesn't ask for new versions. Turn it on in Admin → Sign-up."
+msgstr "Kept 不会检查新版本。可在「管理 → 注册」中开启。"
+
+msgid "Kept got no answer from the backup storage. Check the address, the credentials and the network."
+msgstr "Kept 未收到备份存储的响应。请检查地址、凭据和网络连接。"
+
+msgid "Kept warns at {warnAt}%."
+msgstr "Kept 会在达到 {warnAt}% 时发出警告。"
+
+msgid "Last checked {checked}"
+msgstr "上次检查:{checked}"
+
+msgid "Last drill {lastDrill}"
+msgstr "上次演练:{lastDrill}"
+
+msgid "Last good backup {lastGood}"
+msgstr "上次成功备份:{lastGood}"
+
+msgid "Loading backups"
+msgstr "正在加载备份"
+
+msgid "Loading snapshots"
+msgstr "正在加载快照"
+
+msgid "Locked"
+msgstr "已锁定"
+
+msgid "Monthly"
+msgstr "每月"
+
+msgid "New versions"
+msgstr "新版本"
+
+msgid "Nightly"
+msgstr "每晚"
+
+msgid "No backups yet"
+msgstr "暂无备份"
+
+msgid "No drill yet"
+msgstr "尚未进行恢复演练"
+
+msgid "No good backup yet"
+msgstr "尚无完整可用的备份"
+
+msgid "No releases found"
+msgstr "未找到发布版本"
+
+msgid "No repository there yet"
+msgstr "该路径下尚无存储库"
+
+msgid "No snapshot was taken before the upgrade. The next good backup clears this."
+msgstr "升级前未创建快照。下次成功备份后将清除此提示。"
+
+msgid "No snapshots yet. The first backup makes one."
+msgstr "暂无快照。首次备份时会创建一个快照。"
+
+msgid "No target"
+msgstr "无目标"
+
+msgid "None in the last day"
+msgstr "过去 24 小时内无记录"
+
+msgid "Not known yet"
+msgstr "暂未可知"
+
+msgid "Not made by Kept"
+msgstr "非 Kept 生成"
+
+msgid "Not measured yet"
+msgstr "尚未测量"
+
+msgid "Nothing on this server is backed up. Choose where backups go (another disk, an S3 bucket or an SFTP server) and a password in Backups."
+msgstr "此服务器尚未配置备份。请在“备份”中选择备份目标位置(另一块磁盘、S3 存储桶或 SFTP 服务器)并设置密码。"
+
+msgid "Off. Kept never asks; check the releases page yourself."
+msgstr "已关闭。Kept 不会主动检查更新;请自行查看发布页面。"
+
+msgid "On. Once a day the server asks GitHub for Kept's newest release, sending nothing but the request. Admin → Status says when one is out."
+msgstr "已开启。服务器每天会向 GitHub 查询一次 Kept 最新版本,仅发送查询请求本身。可在「管理 → 状态」查看是否有新版本。"
+
+msgid "Once a month, restore into a scratch database and compare: <0>{command}0>"
+msgstr "建议每月在临时数据库中还原一次并进行比对:<0>{command}0>"
+
+msgid "Open Backups"
+msgstr "打开备份设置"
+
+msgid "Opened the repository with the saved password just now."
+msgstr "刚才已使用保存的密码成功打开仓库。"
+
+msgid "Path-style addresses (most self-hosted stores need this)"
+msgstr "路径风格地址(大多数自托管存储都需要此项)"
+
+msgid "Port"
+msgstr "端口"
+
+msgid "Private key"
+msgstr "私钥"
+
+msgid "private key saved"
+msgstr "私钥已保存"
+
+msgid "Reached"
+msgstr "已达到"
+
+msgid "Region"
+msgstr "区域"
+
+msgid "Release"
+msgstr "版本"
+
+msgid "Repository check"
+msgstr "存储库检查"
+
+msgid "Restore drill"
+msgstr "恢复演练"
+
+msgid "Restoring is a command, not a button: <0>{command}0> (the backup runbook has the steps)."
+msgstr "恢复操作需要通过命令而非按钮执行:<0>{command}0>(具体步骤见备份操作手册)。"
+
+msgid "Revision <0>{revision}0>"
+msgstr "修订版 <0>{revision}0>"
+
+msgid "Run now"
+msgstr "立即运行"
+
+msgid "Running"
+msgstr "运行中"
+
+msgid "Running an older release on a database from <0>{newer}0>"
+msgstr "正在用较旧版本运行来自 <0>{newer}0> 的数据库"
+
+msgid "Runs"
+msgstr "运行记录"
+
+msgid "S3-compatible"
+msgstr "S3 兼容存储"
+
+msgid "Saved, never shown again"
+msgstr "已保存,不再显示"
+
+msgid "Search by error or target"
+msgstr "按错误或目标搜索"
+
+msgid "Search runs"
+msgstr "搜索记录"
+
+msgid "Secret access key"
+msgstr "Secret Access Key"
+
+msgid "secret key saved"
+msgstr "密钥已保存"
+
+msgid "Server"
+msgstr "服务器"
+
+msgid "Set"
+msgstr "已设置"
+
+msgid "Set by the server's environment"
+msgstr "由服务器环境变量设定"
+
+msgid "Set up backups"
+msgstr "设置备份"
+
+msgid "Set, and in the recovery kit"
+msgstr "已设置,且已包含在恢复套件中"
+
+msgid "SFTP"
+msgstr "SFTP"
+
+msgid "Snapshots"
+msgstr "快照"
+
+msgid "Snapshots taken before an upgrade: the last {preUpgrade} are kept."
+msgstr "升级前快照:仅保留最近 {preUpgrade} 份。"
+
+msgid "Some files couldn't be read. The rest are in the snapshot."
+msgstr "部分文件无法读取,其余文件已包含在快照中。"
+
+msgid "Some files don't match their checksums. They were backed up as they are."
+msgstr "部分文件与校验和不符,已按当前内容原样备份。"
+
+msgid "Some locations were left out of the readable copy. The database and files are in the snapshot."
+msgstr "部分空间未包含在可读副本中。数据库和文件均已包含在快照中。"
+
+msgid "Target"
+msgstr "目标"
+
+msgid "The backup failed. The server's log has the details."
+msgstr "备份失败。详情请查看服务器日志。"
+
+msgid "The backup tool couldn't open the repository. Test says why."
+msgstr "备份工具无法打开仓库,测试结果已说明原因。"
+
+msgid "The backup tool failed. The server's log has the details."
+msgstr "备份工具运行失败。详情请查看服务器日志。"
+
+msgid "The bucket keeps earlier versions of every file."
+msgstr "存储桶会保留每个文件的历史版本。"
+
+msgid "The database dump failed. The server's log has the details."
+msgstr "数据库导出失败。详情请查看服务器日志。"
+
+msgid "The backup stopped before it finished: the server restarted or ran out of memory. The next backup runs as usual."
+msgstr "备份在完成前中断:可能是服务器重启或内存不足。下次备份将照常运行。"
+
+msgid "The database dump tool doesn't match the database's version. Use Kept's own image."
+msgstr "数据库导出工具与数据库版本不匹配。请使用 Kept 官方镜像。"
+
+msgid "The dump was much smaller than the last good one. Older snapshots were kept."
+msgstr "导出文件体积远小于上次正常备份,已保留较早的快照。"
+
+msgid "The last check got no answer. Kept asks again tomorrow."
+msgstr "上次检查未收到响应,Kept 将于明天再次检查。"
+
+msgid "The repository is locked by another run. If none is running, {unlock} removes the lock."
+msgstr "仓库正被另一个任务锁定。如果当前没有其他任务运行,点击「{unlock}」即可解除锁定。"
+
+msgid "The repository there was made with another password. Enter that one, or choose an empty folder."
+msgstr "该目录中的备份仓库使用了不同的密码。请输入原密码,或选择一个空文件夹。"
+
+msgid "The repository was made with another password. Set that one in Backups."
+msgstr "该仓库是使用另一个密码创建的。请在「备份」中填写该密码。"
+
+msgid "The server's environment sets that, so it can't be changed here."
+msgstr "该项由服务器环境变量决定,无法在此修改。"
+
+msgid "The server's own key, as ssh-keyscan prints it without the host name. Kept connects to no other."
+msgstr "服务器自身的公钥(即 ssh-keyscan 输出的格式,不含主机名)。Kept 不会连接到其他服务器。"
+
+msgid "The snapshot was taken, but something needs a look. The server's log has the details."
+msgstr "快照已创建,但有情况需要查看。详细信息请见服务器日志。"
+
+msgid "There is no good backup yet"
+msgstr "尚无可用备份"
+
+msgid "There is no repository at the target yet. Test creates one."
+msgstr "目标位置尚未创建仓库。点击测试将自动新建。"
+
+msgid "They need a decision: retry or discard."
+msgstr "需要你决定:重试或放弃。"
+
+msgid "This needs a secure (HTTPS) connection to Kept."
+msgstr "这需要通过安全连接 (HTTPS) 访问 Kept。"
+
+msgid "This server runs <0>{current}0>. Upgrading is the release notes' steps; Kept never updates itself."
+msgstr "当前服务器运行版本为 <0>{current}0>。请按发布说明中的步骤手动升级;Kept 不会自动更新。"
+
+msgid "This server's source code address isn't a GitHub repository, so Kept doesn't ask."
+msgstr "此服务器的源码地址不是 GitHub 仓库,因此 Kept 不会自动检查更新。"
+
+msgid "Too many requests came from this server's address. Kept asks again tomorrow."
+msgstr "来自此服务器地址的请求过多,Kept 将于明天重试。"
+
+msgid "Up to date"
+msgstr "已是最新"
+
+msgid "Updates"
+msgstr "动态更新"
+
+msgid "Upgraded from <0>{from}0> to <1>{to}1> without a backup"
+msgstr "从 <0>{from}0> 升级至 <1>{to}1>(未先备份)"
+
+msgid "Use a backup password of at least 12 characters. A few words are easiest."
+msgstr "请使用至少 12 个字符的备份密码。几个词组合起来最容易记住。"
+
+msgid "User"
+msgstr "用户"
+
+msgid "Weekly"
+msgstr "每周"
+
+msgid "What's new"
+msgstr "更新内容"
+
+msgid "When, and what is kept"
+msgstr "备份时间与保留策略"
+
+msgid "Where backups go"
+msgstr "备份保存位置"
+
+msgid "With S3 file storage, a deleted or overwritten file can only come back if the bucket keeps versions. Turn versioning on in the bucket's settings."
+msgstr "使用 S3 文件存储时,只有在存储桶开启了版本控制的情况下,被删除或覆盖的文件才能恢复。请在存储桶设置中开启版本控制。"
+
+msgid "Wrong password"
+msgstr "密码错误"
+
+msgid "Your export is ready"
+msgstr "你的导出已就绪"
+
+msgid "Your data export is ready"
+msgstr "你的数据导出已就绪"
+
+msgid "Low since {day}"
+msgstr "自 {day} 起处于低库存"
+
+msgid "Kept can't reach that address. Check it for typos."
+msgstr "Kept 无法访问该地址,请检查是否有拼写错误。"
+
+msgid "You have no AI of your own to answer here. Ask from a location's page, where its AI answers."
+msgstr "你尚未配置个人 AI 来在此回答。请在所属空间的页面提问,由该空间的 AI 回答。"
+
+msgid "Webhook added"
+msgstr "已添加 Webhook"
+
+msgid "Webhook changed"
+msgstr "Webhook 已更改"
+
+msgid "Webhook removed"
+msgstr "Webhook 已移除"
+
+msgid "Webhook secret replaced"
+msgstr "Webhook 密钥已更换"
+
+msgid "Receipt read again"
+msgstr "已重新识别收据"
+
+msgid "Other names added"
+msgstr "已添加别名"
+
+msgid "Other names requested for an import"
+msgstr "导入时请求的其他名称"
+
+msgid "Kept set up"
+msgstr "Kept 已完成初始化"
+
+msgid "Instance settings changed"
+msgstr "实例设置已更改"
+
+msgid "Backup made"
+msgstr "已创建备份"
+
+msgid "Backup started by hand"
+msgstr "已手动启动备份"
+
+msgid "Backup settings changed"
+msgstr "备份设置已更改"
+
+msgid "Backup target tested"
+msgstr "备份目标测试完成"
+
+msgid "Restored from a backup"
+msgstr "已从备份恢复"
+
+msgid "Whole instance exported"
+msgstr "已导出整个实例"
+
+msgid "Started on an older version anyway"
+msgstr "依然在旧版本上启动"
+
+msgid "Encryption key replaced"
+msgstr "已更换加密密钥"
+
+msgid "Old encryption key removed"
+msgstr "旧加密密钥已移除"
+
+msgid "Semantic search source changed"
+msgstr "语义搜索来源已更改"
+
+msgid "Recovery kit downloaded"
+msgstr "已下载恢复工具包"
+
+msgid "Checked for updates"
+msgstr "已检查更新"
+
+msgid "New setup code issued"
+msgstr "已签发新的设置码"
+
+msgid "OIDC sign-in settings changed"
+msgstr "OIDC 登录设置已更改"
+
+msgid "Email settings changed"
+msgstr "邮件设置已更改"
+
+msgid "OpenAI says data sent to its API isn't used to train its models unless you opt in, and it keeps abuse-monitoring logs for up to 30 days."
+msgstr "OpenAI 表示,除非你主动选择加入,否则发送到其 API 的数据不会用于训练模型,且滥用监控日志最多保留 30 天。"
+
+msgid "Anthropic says it doesn't use API inputs or outputs to train its models by default, and deletes them within 30 days unless its usage policy or the law needs them kept longer."
+msgstr "Anthropic 表示默认不使用 API 输入或输出训练模型,并会在 30 天内删除数据(除非因使用政策或法律要求需保留更长时间)。"
+
+msgid "Google says that on the Gemini API's paid tier it doesn't use your prompts or responses to improve its products, and logs them for a limited time to catch misuse. On the free tier it uses them to improve its products, and people may read them."
+msgstr "Google 表示,在 Gemini API 付费层级中不会使用你的提示词或回复来改进产品,仅会有限期留存以排查滥用行为;而在免费层级中则会用于改进产品,且可能会被人工审阅。"
+
+msgid "OpenRouter says it logs only the time, the model and token counts, not prompts or responses unless you opt in, and sends requests to providers that log or train on them only if you allow it in its privacy settings."
+msgstr "OpenRouter 表示仅记录时间、模型与 token 用量,除非你主动开启,否则不会记录提示词或响应;只有当你在其隐私设置中允许时,才会将请求转发给会记录或用于训练的服务商。"
+
+msgid "Groq says it doesn't keep inference requests by default, may keep logs for up to 30 days to fix failures or investigate abuse, and isn't permitted to train on them without your permission."
+msgstr "Groq 表示默认不保留推理请求,可能保留日志最多 30 天用于排查故障或调查滥用,且未经你的许可不得用于模型训练。"
+
+msgid "How this server runs"
+msgstr "服务器运行方式"
+
+msgid "Docker Compose"
+msgstr "Docker Compose"
+
+msgid "Docker"
+msgstr "Docker"
+
+msgid "Kubernetes"
+msgstr "Kubernetes"
+
+msgid "Replace the highlighted parts with your own names."
+msgstr "将高亮部分替换为你的实际名称。"
+
+msgid "The code is printed once, on the first start. If the container has been recreated since, issue a new code."
+msgstr "设置码仅在首次启动时打印一次。如果此后容器已被重建,请重新签发设置码。"
+
+msgid "Install guide"
+msgstr "安装指引"
+
+msgid "On a NAS or an app store, search its logs page for <0>KEPT SETUP CODE0>."
+msgstr "在 NAS 或应用商店中,于其日志页面搜索 <0>KEPT SETUP CODE0>。"
+
+msgid "helm install printed this command with your names. The code is printed once: after a container restart add <0>--previous0>; if the pod has been replaced, issue a new code."
+msgstr "helm install 输出的命令中包含你的实例名称。设置码仅打印一次:若容器重启请加上 <0>--previous0>;若 Pod 已被重建,请重新签发设置码。"
+
+msgid "Works only until setup is finished. It replaces the old code and lifts the lockout on wrong codes. It needs the database owner's login: Compose's migrate service has it, and under Helm the pod that runs backups."
+msgstr "仅在完成初始设置前有效。它会替换旧验证码并解除输错次数过多导致的锁定。需要数据库所有者的登录凭据:在 Compose 中位于 migrate 服务,在 Helm 中位于运行备份的 Pod。"
+
+msgid "CLI guide"
+msgstr "CLI 指南"
+
+msgid "This question is more than your AI plan allows in one minute. Choose a model with a higher limit in Settings → AI, or a paid plan."
+msgstr "此问题超出了你的 AI 套餐每分钟允许的额度。请在「设置 → AI」中选择限额更高的模型,或升级为付费套餐。"
+
+msgid "{0} is back"
+msgstr "{0} 已归还"
+
+msgid "{0} went back to {1}"
+msgstr "{0} 已归还给 {1}"
+
+msgid "Mark {0} returned"
+msgstr "将 {0} 标记为已归还"
+
+msgid "Timezone"
+msgstr "时区"
+
+msgid "Dates in this location read in this zone."
+msgstr "此空间中的日期将按该时区解析。"
+
+msgid "New amounts default to this. Existing amounts keep theirs; converted totals need Account → Exchange rates."
+msgstr "新金额将默认使用此币种。现有金额保留原币种;汇总换算需要在「账号 → 汇率」中设置。"
+
+msgid "Back to {0}"
+msgstr "返回 {0}"
+
+msgid "{0, plural, one {The tour added # item to your library.} other {The tour added # items to your library.}}"
+msgstr "{0, plural, one {导览已向你的物品库中添加 # 件物品。} other {导览已向你的物品库中添加 # 件物品。}}"
+
+msgid "{failures, plural, one {# added item couldn't be removed. Check your connection and try Discard again, or Keep it.} other {# added items couldn't be removed. Check your connection and try Discard again, or Keep them.}}"
+msgstr "{failures, plural, one {有 # 个已添加项未能移除。请检查网络连接并重试放弃,或选择保留。} other {有 # 个已添加项未能移除。请检查网络连接并重试放弃,或选择保留。}}"
+
+msgid "Keep what you added?"
+msgstr "保留你刚添加的内容吗?"
+
+msgid "Ended: the account was reclaimed"
+msgstr "已结束:账号已被收回"
+
+msgid "The weekly backup check found a problem"
+msgstr "每周备份检查发现问题"
+
+msgid "Some files are missing from the file storage, so no backup holds them. The server's log names them."
+msgstr "文件存储中缺少部分文件,因此任何备份都不包含它们。服务器日志中列出了这些文件名。"
+
+msgid "Delete my account"
+msgstr "删除我的账号"
+
+msgid "Delete…"
+msgstr "删除…"
+
+msgid "Delete your account"
+msgstr "删除你的账号"
+
+msgid "Checking your account…"
+msgstr "正在检查你的账号…"
+
+msgid "Your account can't be deleted yet"
+msgstr "你的账号暂时无法删除"
+
+msgid "This account was made for you by someone who runs a location. Ask them to remove it."
+msgstr "此账号由某位空间管理员为你创建,请联系对方将其移除。"
+
+msgid "You're the only person who runs this Kept. Make someone else an instance admin first."
+msgstr "你是此 Kept 实例唯一的管理员。请先将其他人设为实例管理员。"
+
+msgid "You own these locations. Hand each one to someone else, or delete it, first."
+msgstr "你是以下空间的拥有者。请先将它们转让给他人或删除。"
+
+msgid "What you added to other people's locations stays there. Your other devices are signed out now."
+msgstr "你在其他人空间中添加的内容会保留在那里。你的其他设备现已退出登录。"
+
+msgid "Keep a copy first?"
+msgstr "要先保留一份副本吗?"
+
+msgid "Your account stays"
+msgstr "你的账号将保留"
+
+msgid "Your account will be deleted on {day}"
+msgstr "你的账号将于 {day} 被删除"
+
+msgid "Keep my account"
+msgstr "保留我的账号"
+
+msgid "Your account is going to be deleted. Keep it to use Kept again."
+msgstr "你的账号即将被删除。保留账号即可继续使用 Kept。"
+
+msgid "Your account can't be deleted yet."
+msgstr "你的账号暂时无法删除。"
+
+msgid "A former member"
+msgstr "前成员"
+
+msgid "Join with Google"
+msgstr "通过 Google 加入"
+
+msgid "That didn't work. Try again."
+msgstr "操作未成功,请重试。"
+
+msgid "Unlinked"
+msgstr "已解除关联"
+
+msgid "Sign-in methods"
+msgstr "登录方式"
+
+msgid "Sign in again first"
+msgstr "请先重新登录"
+
+msgid "Linking or unlinking a sign-in needs a sign-in in the last ten minutes."
+msgstr "关联或取消关联登录方式需要过去 10 分钟内的登录验证。"
+
+msgid "Loading your sign-in methods"
+msgstr "正在加载登录方式"
+
+msgid "Not linked"
+msgstr "未关联"
+
+msgid "Unlink {name}?"
+msgstr "取消关联 {name}?"
+
+msgid "You won't be able to sign in with {name} until you link it again. Your password and passkeys still work."
+msgstr "在重新关联前,你将无法使用 {name} 登录。你的密码和通行密钥仍可正常使用。"
+
+msgid "Unlink"
+msgstr "取消关联"
+
+msgid "Once linked, that account signs you in here. Kept never links one because the email matches."
+msgstr "绑定后即可使用该外部账号登录。Kept 绝不会仅凭邮箱相同就自动关联账号。"
+
+msgid "Sign-in with Google"
+msgstr "使用 Google 登录"
+
+msgid "Make an OAuth client in Google Cloud, set <0>KEPT_GOOGLE_CLIENT_ID0> and <1>KEPT_GOOGLE_CLIENT_SECRET1>, then restart Kept."
+msgstr "请在 Google Cloud 中创建 OAuth 客户端,设置 <0>KEPT_GOOGLE_CLIENT_ID0> 和 <1>KEPT_GOOGLE_CLIENT_SECRET1>,然后重启 Kept。"
+
+msgid "Redirect URI to register with Google"
+msgstr "需在 Google 中注册的重定向 URI"
+
+msgid "Google sign-in reaches only an account already linked to it, or someone invited here. Nobody gets in on their own."
+msgstr "Google 登录仅适用于已关联的账号或受邀加入的人员,未受邀者无法自行注册进入。"
+
+msgid "That server is on a private network, which this Kept doesn't allow. An instance admin can allow it."
+msgstr "该服务器位于内网,而当前 Kept 配置不允许访问内网地址。实例管理员可以允许此项。"
+
+msgid "Kept stops sending to it, and forgets its settings."
+msgstr "Kept 将停止向其发送数据,并清除其设置。"
+
+msgid "Add ntfy"
+msgstr "添加 ntfy"
+
+msgid "Add Telegram"
+msgstr "添加 Telegram"
+
+msgid "You have {MAX_RELAY_CHANNELS}, the most Kept allows."
+msgstr "你已添加 {MAX_RELAY_CHANNELS} 个,达到 Kept 允许的上限。"
+
+msgid "Reminders on your phone through ntfy.sh or your own ntfy server."
+msgstr "通过 ntfy.sh 或你自建的 ntfy 服务器在手机上接收提醒。"
+
+msgid "Reminders in a Telegram chat, sent by a bot you make."
+msgstr "由你创建的 Telegram 机器人在聊天中发送提醒。"
+
+msgid "ntfy.sh, or the address of your own ntfy server."
+msgstr "填写 ntfy.sh 或你自建的 ntfy 服务器地址。"
+
+msgid "Topic"
+msgstr "主题"
+
+msgid "Letters, digits, - and _. On ntfy.sh anyone who knows it can read it, so make it hard to guess."
+msgstr "仅限字母、数字、- 和 _。在 ntfy.sh 上任何知道主题名称的人都能读取消息,请设置得不易猜测。"
+
+msgid "Access token"
+msgstr "访问令牌"
+
+msgid "Optional: for a topic that needs one."
+msgstr "可选:用于需要主题的推送通道。"
+
+msgid "Bot token"
+msgstr "机器人令牌(Bot token)"
+
+msgid "From @BotFather in Telegram, when you make the bot."
+msgstr "在 Telegram 中通过 @BotFather 创建机器人时获取。"
+
+msgid "Chat ID"
+msgstr "Chat ID"
+
+msgid "Your chat with the bot, a group's number, or a channel's @name. Send the bot a message first."
+msgstr "填入你与机器人的私聊 ID、群组 ID 或频道 @名称。请先向机器人发送一条消息。"
+
+msgid "Optional, to tell them apart."
+msgstr "可选,用于区分不同项目。"
+
+msgid "Kept keeps these settings encrypted and never shows them again."
+msgstr "Kept 会加密保存这些设置,之后不会再明文显示。"
+
+msgid "It's also on its way to your email."
+msgstr "同时也已发送至你的邮箱。"
+
+msgid "Kept emails this location's inventory every Monday morning."
+msgstr "Kept 会在每周一早上通过邮件发送此空间的物品清单。"
+
+msgid "Kept emails this location's inventory on the 1st of every month."
+msgstr "Kept 会在每月 1 日通过邮件发送此空间的物品清单。"
+
+msgid "Email it to me"
+msgstr "发送到我的邮箱"
+
+msgid "Send it again"
+msgstr "重新发送"
+
+msgid "Never"
+msgstr "从不"
+
+msgid "Every week"
+msgstr "每周"
+
+msgid "Every month"
+msgstr "每月"
+
+msgid "Emailed to you: the whole location, with photos, as it is that day. Stop it in Settings → Me → Notifications."
+msgstr "已通过邮件发送给你:截至当日的整个空间数据(含照片)。可在「设置 → 我 → 通知」中关闭。"
+
+msgid "Skipped: you'd made five reports that hour."
+msgstr "已跳过:过去一小时内已生成五份报告。"
+
+msgid "Skipped: that part of Kept is off in this location."
+msgstr "已跳过:此空间未开启 Kept 的该功能模块。"
+
+msgid "Skipped: you can't make this report there any more."
+msgstr "已跳过:你已无权在此处生成该报告。"
+
+msgid "Stop this report?"
+msgstr "要停止此报告吗?"
+
+msgid "Kept stops emailing it. You can print it any time."
+msgstr "Kept 将不再通过邮件发送该资料。你仍可随时打印。"
+
+msgid "Stop"
+msgstr "停止"
+
+msgid "Couldn't stop it"
+msgstr "无法停止"
+
+msgid "Scheduled reports"
+msgstr "定期报告"
+
+msgid "Inventory of <0>{name}0>"
+msgstr "<0>{name}0> 的物品清单"
+
+msgid "Insurance report of <0>{name}0>"
+msgstr "<0>{name}0> 的保险报告"
+
+msgid "Every Monday"
+msgstr "每周一"
+
+msgid "On the 1st of every month"
+msgstr "每月 1 日"
+
+msgid "Last sent {0}"
+msgstr "上次发送:{0}"
+
+msgid "Import from LubeLogger"
+msgstr "从 LubeLogger 导入"
+
+msgid "This isn't a LubeLogger export of fuel, services or odometer."
+msgstr "这不是 LubeLogger 的燃油、保养或里程表导出文件。"
+
+msgid "Kept can't read this file. Export it from LubeLogger again as CSV."
+msgstr "Kept 无法读取此文件。请从 LubeLogger 重新导出为 CSV。"
+
+msgid "Kept can't read this file."
+msgstr "Kept 无法读取该文件。"
+
+msgid "Imported {0} records"
+msgstr "已导入 {0} 条记录"
+
+msgid "In LubeLogger, export this vehicle's fuel, service or odometer records as CSV, then choose the file here. One file at a time; importing the same one again adds nothing."
+msgstr "在 LubeLogger 中将此车辆的加油、保养或里程表记录导出为 CSV,然后在此选择文件。每次上传一个文件;重复导入同一文件不会新增记录。"
+
+msgid "{kindName}: {0} rows"
+msgstr "{kindName}:{0} 行"
+
+msgid "Dates are written"
+msgstr "日期格式"
+
+msgid "Month first"
+msgstr "月份在前"
+
+msgid "Day first"
+msgstr "日在前"
+
+msgid "Year first"
+msgstr "年份在前"
+
+msgid "Decimal mark"
+msgstr "小数点符号"
+
+msgid "Fuel is in"
+msgstr "已记录加油"
+
+msgid "Gallons"
+msgstr "加仑"
+
+msgid "Check"
+msgstr "检查"
+
+msgid "no date Kept can read"
+msgstr "未能识别到有效日期"
+
+msgid "no amount of fuel"
+msgstr "无加油量"
+
+msgid "no description"
+msgstr "无描述"
+
+msgid "no odometer reading"
+msgstr "无里程表读数"
+
+msgid "this vehicle has no odometer"
+msgstr "此车辆没有里程表"
+
+msgid "the odometer goes backwards"
+msgstr "里程表读数出现倒退"
+
+msgid "a cost below zero"
+msgstr "低于零的费用"
+
+msgid "Kept refused it"
+msgstr "Kept 已拒绝"
+
+msgid "What it will do"
+msgstr "将会执行的操作"
+
+msgid "Add {0}. Already here: {1}. Can't add: {2}."
+msgstr "添加 {0}。已存在:{1}。无法添加:{2}。"
+
+msgid "Row {0}: {1}"
+msgstr "第 {0} 行:{1}"
+
+msgid "Several things in one photo"
+msgstr "单张照片中包含多件物品"
+
+msgid "Find several things in a photo"
+msgstr "从一张照片中识别多件物品"
+
+msgid "On. Each thing AI finds in a photo becomes its own draft, with its own picture cut from the photo."
+msgstr "已开启。AI 在照片中识别出的每件物品都会单独生成草稿,并自动从原图中裁剪出对应图片。"
+
+msgid "Off. One photo, one thing."
+msgstr "关闭。每张照片对应一件物品。"
+
+msgid "How well the pictures are cut depends on the AI provider. Check a few drafts after turning this on."
+msgstr "图片裁切效果取决于 AI 服务商。开启后请抽查几份草稿。"
+
+msgid "Email-in"
+msgstr "邮件收件导入"
+
+msgid "That address is on a private network. An instance admin can allow it in Admin → Settings."
+msgstr "该地址位于私有网络中。实例管理员可在“管理 → 设置”中允许访问私有地址。"
+
+msgid "Kept couldn't reach that server. Check the host and port."
+msgstr "Kept 无法连接到该服务器。请检查主机和端口。"
+
+msgid "The server's encryption didn't check out. Check the host and the security."
+msgstr "服务器加密校验未通过。请检查主机名与安全设置。"
+
+msgid "The mailbox refused the user name or password."
+msgstr "邮箱拒绝了该用户名或密码。"
+
+msgid "That folder doesn't exist in the mailbox."
+msgstr "邮箱中不存在该文件夹。"
+
+msgid "The server took too long to answer."
+msgstr "服务器响应超时。"
+
+msgid "Kept couldn't sign in to the mailbox."
+msgstr "Kept 无法登录该邮箱。"
+
+msgid "The person who connected it no longer administers this location."
+msgstr "连接该服务的人已不再担任此空间管理员。"
+
+msgid "Draft receipt"
+msgstr "收据草稿"
+
+msgid "No receipt in it"
+msgstr "其中没有收据"
+
+msgid "Sender not allowed"
+msgstr "发件人不在允许列表中"
+
+msgid "Too large"
+msgstr "文件过大"
+
+msgid "Couldn't be read"
+msgstr "无法识别"
+
+msgid "The mailbox works"
+msgstr "邮箱连接正常"
+
+msgid "Mailbox removed"
+msgstr "邮箱已移除"
+
+msgid "Remove this mailbox?"
+msgstr "要移除此邮箱吗?"
+
+msgid "Kept stops checking it. The receipts it already made stay."
+msgstr "Kept 将停止检查该邮箱,但已生成的收据会保留。"
+
+msgid "Mailbox"
+msgstr "收件邮箱"
+
+msgid "Kept stopped checking this mailbox"
+msgstr "Kept 已停止检查此邮箱"
+
+msgid "Save it again to turn it back on."
+msgstr "重新保存即可再次启用。"
+
+msgid "The last check failed"
+msgstr "上次检查失败"
+
+msgid "<0>{0}0> · folder <1>{1}1>"
+msgstr "<0>{0}0> · 文件夹 <1>{1}1>"
+
+msgid "Checked {0}"
+msgstr "已检查 {0}"
+
+msgid "Not checked yet. Kept checks every 10 minutes."
+msgstr "尚未检查。Kept 每 10 分钟检查一次。"
+
+msgid "Connected by {0}"
+msgstr "由 {0} 连接"
+
+msgid "Mailbox saved"
+msgstr "已保存邮箱配置"
+
+msgid "Mailbox connected"
+msgstr "邮箱已连接"
+
+msgid "Change the mailbox"
+msgstr "更换邮箱"
+
+msgid "Connect a mailbox"
+msgstr "连接邮箱"
+
+msgid "Kept checks a folder in a mailbox you already have, every 10 minutes. Each message's photos and PDFs, or its text when it has none, become a draft receipt in the Inbox. Only mail that arrives after you connect is read, and nothing in the mailbox is changed."
+msgstr "Kept 每 10 分钟检查一次你已有邮箱中的指定文件夹。每封邮件的照片与 PDF(若无附件则取正文)会作为收据草稿进入收件箱。仅读取连接后收到的新邮件,且不会对邮箱做任何修改。"
+
+msgid "IMAP server"
+msgstr "IMAP 服务器"
+
+msgid "For example imap.gmail.com or imap.fastmail.com."
+msgstr "例如 imap.gmail.com 或 imap.fastmail.com。"
+
+msgid "TLS (993)"
+msgstr "TLS (993)"
+
+msgid "STARTTLS (143)"
+msgstr "STARTTLS (143)"
+
+msgid "User name"
+msgstr "用户名"
+
+msgid "Saved. Leave it empty to keep it."
+msgstr "已保存。留空表示保持当前值。"
+
+msgid "An app password, if your provider has them."
+msgstr "应用专用密码(如邮箱服务商提供)。"
+
+msgid "Make a folder for receipts and send them there with a filter."
+msgstr "创建一个收据文件夹,并通过过滤规则自动将邮件归入其中。"
+
+msgid "Only from these senders"
+msgstr "仅限以下发件人"
+
+msgid "Optional, comma-separated. A filter against noise, not a security check: a From address can be forged."
+msgstr "可选,以逗号分隔。仅用于过滤杂信,并非安全校验:发件人地址可能被伪造。"
+
+msgid "Kept couldn't connect"
+msgstr "Kept 无法连接"
+
+msgid "Recent mail"
+msgstr "近期邮件"
+
+msgid "Open the Inbox"
+msgstr "打开收件箱"
+
+msgid "No mail read yet"
+msgstr "尚未读取任何邮件"
+
+msgid "Messages that arrive in the folder show here once Kept has read them."
+msgstr "到达该文件夹的邮件在被 Kept 读取后会显示在这里。"
+
+msgid "Add Apprise"
+msgstr "添加 Apprise"
+
+msgid "Reminders to Discord, Slack, Matrix, Signal and over 100 other services, through this server's Apprise."
+msgstr "通过此服务器的 Apprise,将提醒推送至 Discord、Slack、Matrix、Signal 等 100 多种服务。"
+
+msgid "Apprise URLs"
+msgstr "Apprise URL"
+
+msgid "One or more, separated by spaces or commas, like discord://… or mailto://…. Apprise's documentation lists every service."
+msgstr "可填写一个或多个地址,用空格或逗号分隔,例如 discord://… 或 mailto://…。所有支持的服务请参见 Apprise 文档。"
+
+msgid "Condition reports"
+msgstr "成色与状态报告"
+
+msgid "Move-in"
+msgstr "迁入"
+
+msgid "Move-out"
+msgstr "搬出"
+
+msgid "Damaged"
+msgstr "已损坏"
+
+msgid "Condition report PDF"
+msgstr "状态报告 PDF"
+
+msgid "Both walk-throughs room by room, the earlier one first: each room's condition, note and photos, with the time Kept received each photo."
+msgstr "按房间顺序展示两次巡检(较早的在前):包含每个房间的状况、备注与照片,以及 Kept 收到每张照片的时间。"
+
+msgid "Each room's condition, note and photos, with the time Kept received each photo."
+msgstr "每个房间的状况、备注与照片,以及 Kept 收到每张照片的时间。"
+
+msgid "This report isn't finished, and the PDF says so."
+msgstr "此报告尚未完成,导出的 PDF 中也会如此标明。"
+
+msgid "This report is finished, so it can't change."
+msgstr "此报告已完成,无法再修改。"
+
+msgid "Condition report"
+msgstr "状况报告"
+
+msgid "Finished by <0>{0}0>, {1}"
+msgstr "由 <0>{0}0> 完成于 {1}"
+
+msgid "Not finished"
+msgstr "未完成"
+
+msgid "Started by <0>{0}0>"
+msgstr "由 <0>{0}0> 发起"
+
+msgid "Finish this report?"
+msgstr "要完成此报告吗?"
+
+msgid "It is locked once finished: nothing in it can change, and its photos stay as they are."
+msgstr "完成后将锁定:其中内容无法修改,照片也会保持原样。"
+
+msgid "Finish"
+msgstr "完成"
+
+msgid "Delete this report?"
+msgstr "要删除此报告吗?"
+
+msgid "Its rooms, notes and photos go with it. This can't be undone."
+msgstr "其中的房间、备注和照片会一并删除。此操作无法撤销。"
+
+msgid "Compare with"
+msgstr "对比"
+
+msgid "Keys handed over, meter readings, who was there"
+msgstr "钥匙交接、表计读数及当时在场人员"
+
+msgid "No rooms yet. Add the first one below."
+msgstr "暂无房间,请在下方添加第一个房间。"
+
+msgid "Remove {0} from this report?"
+msgstr "从该报告中移除 {0}?"
+
+msgid "Its note and photos go with it."
+msgstr "其备注和照片也会一并跟随。"
+
+msgid "Marks, damage, what works and what doesn't"
+msgstr "划痕、损坏、正常功能与故障说明"
+
+msgid "Condition not recorded"
+msgstr "未记录成色状态"
+
+msgid "Add photos"
+msgstr "添加照片"
+
+msgid "A room holds {MAX_ROOM_PHOTOS} photos. Remove one to add another."
+msgstr "一个房间最多保存 {MAX_ROOM_PHOTOS} 张照片。请先移除一张再添加。"
+
+msgid "Added {when}"
+msgstr "添加于 {when}"
+
+msgid "Remove this photo?"
+msgstr "移除这张照片?"
+
+msgid "Another room"
+msgstr "其他房间"
+
+msgid "Balcony, hallway, storage"
+msgstr "阳台、走廊、储藏室"
+
+msgid "Add room"
+msgstr "添加房间"
+
+msgid "Room by room"
+msgstr "逐个房间"
+
+msgid "Not in this report."
+msgstr "不在本报告中。"
+
+msgid "{0, plural, one {# room} other {# rooms}}"
+msgstr "{0, plural, one {# 个房间} other {# 个房间}}"
+
+msgid "Finished"
+msgstr "已完成"
+
+msgid "New report"
+msgstr "新建报告"
+
+msgid "Needs a connection: starting a report waits until you're back online."
+msgstr "需要联网:生成报告将在恢复网络后进行。"
+
+msgid "Search condition reports"
+msgstr "搜索成色报告"
+
+msgid "Kind, location or notes"
+msgstr "类型、空间或备注"
+
+msgid "No condition reports"
+msgstr "暂无状况报告"
+
+msgid "Renting? When you move in, walk through each room and record how you found it, with photos. Do the same when you move out, and print both side by side if the deposit is disputed."
+msgstr "租房入住时,建议逐个房间走一圈并拍照记录房屋现状。退租时再做一次,如果押金有争议,可以把两份报告并排打印出来对比。"
+
+msgid "New condition report"
+msgstr "新建状况报告"
+
+msgid "Pick the day of the walk-through."
+msgstr "选择巡检日期。"
+
+msgid "It starts with the location's rooms. Add any it missed, and record each one with photos."
+msgstr "默认从该空间的现有房间开始。如有遗漏可自行添加,并逐个拍照记录现状。"
+
+msgid "Day of the walk-through"
+msgstr "巡检日期"
+
+msgid "Shared from Kept · read-only"
+msgstr "来自 Kept 的共享 · 只读"
+
+msgid "Shared with you"
+msgstr "与你分享的"
+
+msgid "This link has expired"
+msgstr "此链接已过期"
+
+msgid "Ask the person who shared it for a new one."
+msgstr "请联系分享该链接的人获取新链接。"
+
+msgid "Couldn't open this link"
+msgstr "无法打开此链接"
+
+msgid "Share a read-only link"
+msgstr "分享只读链接"
+
+msgid "For someone without an account; it expires"
+msgstr "供无账户人员使用;链接会过期"
+
+msgid "Share links"
+msgstr "分享链接"
+
+msgid "No longer here"
+msgstr "已不在此处"
+
+msgid "Read-only links to a box, a place or a list, for someone without an account. Make one from a box's or a place's page, or from Search."
+msgstr "指向箱子、位置或列表的只读链接,供没有账户的人查看。可在箱子、位置页面或搜索结果中创建。"
+
+msgid "Search share links"
+msgstr "搜索共享链接"
+
+msgid "No share links here"
+msgstr "此处暂无分享链接"
+
+msgid "Open a box or a place and choose Share a read-only link, or share a search's list from Search."
+msgstr "打开某个收纳箱或位置并选择「共享只读链接」,或在「搜索」中共享搜索结果列表。"
+
+msgid "Revoked {revokedOn}"
+msgstr "撤销于 {revokedOn}"
+
+msgid "Expired {until}"
+msgstr "已于 {until} 过期"
+
+msgid "{0, plural, =0 {Not opened yet} one {Opened once} other {Opened # times}}"
+msgstr "{0, plural, =0 {尚未打开过} one {打开过 1 次} other {打开过 # 次}}"
+
+msgid "Last opened {opened}"
+msgstr "上次打开 {opened}"
+
+msgid "It stopped because <0>{0}0> no longer runs this location."
+msgstr "已停止,因为 <0>{0}0> 不再管理此空间。"
+
+msgid "Shared by <0>{0}0>"
+msgstr "由 <0>{0}0> 分享"
+
+msgid "Preview as recipient"
+msgstr "以接收者视角预览"
+
+msgid "Revoke this link?"
+msgstr "要撤销此链接吗?"
+
+msgid "Anyone who opens it sees \"This link has expired\" from now on. It can't be turned back on."
+msgstr "此后任何人打开此链接都会看到“此链接已过期”,且无法重新启用。"
+
+msgid "Remove the state and price filters to share this list."
+msgstr "移除状态和价格筛选条件后即可分享此列表。"
+
+msgid "Filter it to one location you run to share this list."
+msgstr "请先筛选为你管理下的单个空间,然后再分享此列表。"
+
+msgid "Share this list"
+msgstr "分享此列表"
+
+msgid "Give the list a name."
+msgstr "为列表起个名字。"
+
+msgid "Anyone with the link sees what this search finds in <0>{locationName}0> when they open it. No account needed."
+msgstr "任何拥有此链接的人无需登录,即可在打开时查看此搜索在 <0>{locationName}0> 中找到的结果。"
+
+msgid "Anyone with the link sees <0>{name}0> and everything in it. No account needed."
+msgstr "拥有链接的任何人均可查看 <0>{name}0> 及其中的全部内容,无需账号。"
+
+msgid "Name on the page"
+msgstr "页面显示名称"
+
+msgid "Works for"
+msgstr "适用于"
+
+msgid "Make link"
+msgstr "生成链接"
+
+msgid "Anyone with this link can open it until {until}."
+msgstr "持有此链接的任何人都可在 {until} 前打开。"
+
+msgid "Copy it now. Kept shows this link once; make a new one if it's lost."
+msgstr "请立即复制。Kept 仅显示此链接一次;如不慎丢失,请重新生成。"
+
+msgid "See this location's share links"
+msgstr "查看此空间的分享链接"
+
+msgid "This link works until {until}."
+msgstr "此链接有效期至 {until}。"
+
+msgid "A link shows the first {0} of them, A to Z."
+msgstr "分享链接按 A–Z 顺序显示前 {0} 项。"
+
+msgid "Quantity {quantity}"
+msgstr "数量 {quantity}"
+
+msgid "Search this list"
+msgstr "搜索此列表"
+
+msgid "by where"
+msgstr "按位置"
+
+msgid "Box"
+msgstr "箱子"
+
+msgid "A day"
+msgstr "一天"
+
+msgid "A week"
+msgstr "一周"
+
+msgid "30 days"
+msgstr "30 天"
+
+msgid "90 days"
+msgstr "90 天"
+
+msgid "A year"
+msgstr "一年"
+
+msgid "They see names, photos, types, where things are, quantities, condition and notes. Never prices, serial numbers, secrets, people, loans or documents."
+msgstr "对方可查看物品名称、照片、类型、所在位置、数量、成色和备注;绝不会看到价格、序列号、密钥、联系人、借出记录或文档。"
+
+msgid "Share link made"
+msgstr "分享链接已创建"
+
+msgid "Share link revoked"
+msgstr "已撤销分享链接"
+
+msgid "Only {left} left of {name}."
+msgstr "{name} 仅剩 {left}。"
+
+msgid "Only {left} left."
+msgstr "仅剩 {left} 个。"
+
+msgid "From stock"
+msgstr "来自库存"
+
+msgid "Optional. Saving takes the quantity off its count."
+msgstr "可选。保存后将从库存总数中扣除相应数量。"
+
+msgid "Not from stock"
+msgstr "非消耗品"
+
+msgid "{left} left"
+msgstr "剩余 {left}"
+
+msgid "Used {name} in a service of {service}"
+msgstr "在 {service} 维护中使用了 {name}"
+
+msgid "Put {name} back from a service of {service}"
+msgstr "将 {name} 从“{service}”维护中放回在用状态"
+
+msgid "Go to <0>{0}0>"
+msgstr "前往 <0>{0}0>"
+
+msgid "Amounts leave out {names}: money is hidden from you there."
+msgstr "金额统计中未包含 {names}:你在该空间无权查看价格。"
+
+msgid "Insights is off in your locations"
+msgstr "你的空间未开启统计洞察功能"
+
+msgid "Insights is part of Money. An owner or admin turns Money on in the location's settings, under What to track."
+msgstr "「消费洞察」属于「资金财务」模块。空间所有者或管理员可在空间设置的「追踪内容」下开启该功能。"
+
+msgid "Loading insights"
+msgstr "正在加载消费洞察"
+
+msgid "Money is off here"
+msgstr "此空间已关闭金额功能"
+
+msgid "Insights shows the locations where Money is on. Pick another location."
+msgstr "统计洞察仅显示开启了「金额」功能的空间。请选择其他空间。"
+
+msgid "Spending on things"
+msgstr "物品支出"
+
+msgid "No purchases yet"
+msgstr "暂无购买记录"
+
+msgid "Capture a receipt"
+msgstr "拍摄收据"
+
+msgid "Receipts you capture or add to things show up here, by the year you bought."
+msgstr "你采集或添加到物品上的收据会按购买年份显示在这里。"
+
+msgid "Spent"
+msgstr "已支出"
+
+msgid "Purchases"
+msgstr "购买记录"
+
+msgid "{0, plural, one {# purchase} other {# purchases}}"
+msgstr "{0, plural, one {# 笔购买记录} other {# 笔购买记录}}"
+
+msgid "purchases"
+msgstr "购买记录"
+
+msgid "not compared with full years"
+msgstr "未与完整年份对比"
+
+msgid "Spent per year. Arrow keys move between years."
+msgstr "每年支出。使用方向键可在年份间切换。"
+
+msgid "Purchases per year. Arrow keys move between years."
+msgstr "按年统计的购买记录。使用方向键可在年份之间切换。"
+
+msgid "No full years yet."
+msgstr "尚无完整年份记录。"
+
+msgid "Spent per year, {currency}"
+msgstr "年支出({currency})"
+
+msgid "Purchases per year"
+msgstr "每年购买统计"
+
+msgid "Year"
+msgstr "年"
+
+msgid "{unpriced, plural, one {# purchase has no amount and isn't in the totals.} other {# purchases have no amount and aren't in the totals.}}"
+msgstr "{unpriced, plural, one {# 条购买记录没有金额,未计入总计。} other {# 条购买记录没有金额,未计入总计。}}"
+
+msgid "Value by place"
+msgstr "按位置统计价值"
+
+msgid "Each thing in use at its latest valuation. Things without one count, but add nothing."
+msgstr "按每件在用物品的最新估值汇总。没有估值的物品也会计入件数,但不计入金额。"
+
+msgid "Valued: {0} of {1} things"
+msgstr "已估值:{0} / {1} 件物品"
+
+msgid "No things yet."
+msgstr "暂无物品。"
+
+msgid "Other places ({0})"
+msgstr "其他位置({0})"
+
+msgid "{0} of {1} valued"
+msgstr "{0} / {1} 已估值"
+
+msgid "Vehicle costs"
+msgstr "车辆费用"
+
+msgid "No vehicles yet."
+msgstr "暂无车辆。"
+
+msgid "Each vehicle per year, {currency}"
+msgstr "每辆车每年,{currency}"
+
+msgid "Each vehicle per year"
+msgstr "每辆车按年统计"
+
+msgid "(no longer in use)"
+msgstr "(已停用)"
+
+msgid "Fills: {0}, services: {1}"
+msgstr "加油:{0},保养:{1}"
+
+msgid "See all vehicles ({0} more)"
+msgstr "查看全部车辆(还有 {0} 辆)"
+
+msgid "Ending soon"
+msgstr "即将结束"
+
+msgid "Cover ended"
+msgstr "保障已结束"
+
+msgid "Under warranty"
+msgstr "保修期内"
+
+msgid "Warranty coverage"
+msgstr "保修范围"
+
+msgid "Covered now: {0} of {1} things"
+msgstr "当前已承保:{0} / {1} 件物品"
+
+msgid "See all on Expiring"
+msgstr "在「即将到期」中查看全部"
+
+msgid "cost {0}, covered {1}"
+msgstr "费用 {0},承保 {1}"
+
+msgid "Repairs resolved, {year}: {0}"
+msgstr "{year} 年已解决维修:{0}"
+
+msgid "{left} left, keep at least {min}"
+msgstr "剩余 {left},至少保留 {min}"
+
+msgid "someone"
+msgstr "某人"
+
+msgid "Lent to {who}"
+msgstr "借给 {who}"
+
+msgid "Lent to {who}, back by {back}"
+msgstr "借给 {who},应于 {back} 归还"
+
+msgid "{what}: overdue since {when}"
+msgstr "{what}:自 {when} 起已逾期"
+
+msgid "{what}: due {when}"
+msgstr "{what}:到期 {when}"
+
+msgid "QR label for {printed}"
+msgstr "{printed} 的二维码标签"
+
+msgid "Label of this place"
+msgstr "此位置的标签"
+
+msgid "Label of this thing"
+msgstr "此物品的标签"
+
+msgid "Serial"
+msgstr "序列号"
+
+msgid "No photo yet"
+msgstr "暂无照片"
+
+msgid "{n, plural, one {# place in it} other {# places in it}}"
+msgstr "{n, plural, one {内含 # 个位置} other {内含 # 个位置}}"
+
+msgid "Open the place"
+msgstr "打开该位置"
+
+msgid "Nothing matches."
+msgstr "没有匹配的结果。"
+
+msgid "{w} × {d} m"
+msgstr "{w} × {d} 米"
+
+msgid "What’s here · {0}"
+msgstr "此处物品 · {0}"
+
+msgid "Put on the map"
+msgstr "放到平面图上"
+
+msgid "Find a thing in {0}"
+msgstr "在 {0} 中查找物品"
+
+msgid "Find a thing to put on the map"
+msgstr "找一件物品放到平面图上"
+
+msgid "Everything here is on the map."
+msgstr "这里的所有项目都已在平面图上。"
+
+msgid "on {host}"
+msgstr "位于 {host}"
+
+msgid "{c} running low inside"
+msgstr "内有 {c} 项余量不足"
+
+msgid "{c} lent out inside"
+msgstr "内部有 {c} 件已借出"
+
+msgid "{c} due inside"
+msgstr "内有 {c} 项到期"
+
+msgid "Down to {0}"
+msgstr "下调至 {0}"
+
+msgid "Inside · {n}"
+msgstr "内部 · {n}"
+
+msgid "Turn"
+msgstr "转换"
+
+msgid "Take off the map"
+msgstr "从平面图移除"
+
+msgid "Less"
+msgstr "收起"
+
+msgid "{n, plural, one {# thing inside} other {# things inside}}"
+msgstr "{n, plural, one {内部有 # 件物品} other {内部有 # 件物品}}"
+
+msgid "On it"
+msgstr "正在处理"
+
+msgid "Find inside {0}"
+msgstr "在 {0} 内查找"
+
+msgid "Find inside"
+msgstr "在内部查找"
+
+msgid "Nothing in it yet."
+msgstr "里面暂无内容。"
+
+msgid "Sofa"
+msgstr "沙发"
+
+msgid "Armchair"
+msgstr "扶手椅"
+
+msgid "Coffee table"
+msgstr "茶几"
+
+msgid "TV stand"
+msgstr "电视柜"
+
+msgid "Cube shelf"
+msgstr "格子柜"
+
+msgid "Tall plant"
+msgstr "大型绿植"
+
+msgid "Plant"
+msgstr "绿植"
+
+msgid "Succulent"
+msgstr "多肉植物"
+
+msgid "Dining chair"
+msgstr "餐椅"
+
+msgid "Chest of drawers"
+msgstr "五斗柜"
+
+msgid "Bedside table"
+msgstr "床头柜"
+
+msgid "Metal shelf"
+msgstr "金属货架"
+
+msgid "Tool cart"
+msgstr "工具车"
+
+msgid "Drill"
+msgstr "电钻"
+
+msgid "Moving box"
+msgstr "搬家箱"
+
+msgid "Crate"
+msgstr "储物箱"
+
+msgid "Basket"
+msgstr "收纳篮"
+
+msgid "Bistro set"
+msgstr "休闲小桌椅"
+
+msgid "Plastic chair"
+msgstr "塑料椅"
+
+msgid "Planter"
+msgstr "花箱"
+
+msgid "Long planter"
+msgstr "长条花箱"
+
+msgid "AC outdoor unit"
+msgstr "空调外机"
+
+msgid "Watering can"
+msgstr "浇水壶"
+
+msgid "TV"
+msgstr "电视"
+
+msgid "Bookshelf"
+msgstr "书架"
+
+msgid "Cube storage"
+msgstr "格子柜"
+
+msgid "Tall bookcase"
+msgstr "高书柜"
+
+msgid "Floor lamp"
+msgstr "落地灯"
+
+msgid "Kitchen counter"
+msgstr "厨房台面"
+
+msgid "Sink counter"
+msgstr "水槽台面"
+
+msgid "Fridge"
+msgstr "冰箱"
+
+msgid "Coffee machine"
+msgstr "咖啡机"
+
+msgid "Microwave"
+msgstr "微波炉"
+
+msgid "Dining table"
+msgstr "餐桌"
+
+msgid "Bed"
+msgstr "床"
+
+msgid "Wardrobe"
+msgstr "衣柜"
+
+msgid "Table lamp"
+msgstr "台灯"
+
+msgid "Desk"
+msgstr "书桌"
+
+msgid "Monitor"
+msgstr "显示器"
+
+msgid "Laptop"
+msgstr "笔记本电脑"
+
+msgid "Desk chair"
+msgstr "办公椅"
+
+msgid "Filing cabinet"
+msgstr "文件柜"
+
+msgid "Storage box"
+msgstr "储物箱"
+
+msgid "Washing machine"
+msgstr "洗衣机"
+
+msgid "Workbench"
+msgstr "工作台"
+
+msgid "Bike"
+msgstr "自行车"
+
+msgid "Water tank"
+msgstr "水箱"
+
+msgid "Satellite dish"
+msgstr "卫星天线"
+
+msgid "Stairs"
+msgstr "楼梯"
+
+msgid "Stairwell"
+msgstr "楼梯间"
+
+msgid "Area"
+msgstr "面积"
+
+msgid "Small thing"
+msgstr "小件物品"
+
+msgid "Terrace"
+msgstr "露台"
+
+msgid "Garden"
+msgstr "花园"
+
+msgid "Wood"
+msgstr "木质"
+
+msgid "Tiles"
+msgstr "磁贴"
+
+msgid "Concrete"
+msgstr "混凝土"
+
+msgid "Deck"
+msgstr "露台"
+
+msgid "Grass"
+msgstr "草地"
+
+msgid "Not on a floor"
+msgstr "不在任何楼层"
+
+msgid "on it: {x}"
+msgstr "上面有:{x}"
+
+msgid "+{n} more"
+msgstr "还有 {n} 项"
+
+msgid "{n} inside"
+msgstr "内含 {n} 项"
+
+msgid "click to open"
+msgstr "点击打开"
+
+msgid "click to change floor"
+msgstr "点击切换楼层"
+
+msgid "Room {n}"
+msgstr "房间 {n}"
+
+msgid "Couldn’t add the room"
+msgstr "无法添加房间"
+
+msgid "Floor {n}"
+msgstr "第 {n} 层"
+
+msgid "Room 1"
+msgstr "房间 1"
+
+msgid "Couldn’t add the floor"
+msgstr "无法添加楼层"
+
+msgid "Throw away these changes?"
+msgstr "放弃这些更改?"
+
+msgid "The map goes back to how it was. Rooms and floors you added stay in Kept."
+msgstr "平面图将恢复原样。你已添加的房间和楼层仍会保留在 Kept 中。"
+
+msgid "Throw away"
+msgstr "丢弃"
+
+msgid "Map arranged"
+msgstr "已整理地图布局"
+
+msgid "Someone arranged this map since you opened it"
+msgstr "自你打开后,有人调整了此平面地图的布局"
+
+msgid "Couldn’t save the map"
+msgstr "无法保存平面图"
+
+msgid "Drag on empty ground to draw a new room on this floor."
+msgstr "在空白区域拖拽即可在此楼层绘制新房间。"
+
+msgid "Rooms can’t overlap. Draw on empty ground."
+msgstr "房间不能重叠,请在空白区域绘制。"
+
+msgid "Map of {name}"
+msgstr "{name} 平面图"
+
+msgid "This browser can’t draw the map. The list below has everything on it."
+msgstr "此浏览器无法绘制地图。下方列表包含所有内容。"
+
+msgid "Where you are on the map"
+msgstr "你在平面图上的位置"
+
+msgid "View"
+msgstr "查看"
+
+msgid "3D"
+msgstr "3D"
+
+msgid "Plan"
+msgstr "平面图"
+
+msgid "Saving…"
+msgstr "正在保存…"
+
+msgid "Arrange"
+msgstr "调整布局"
+
+msgid "Pins"
+msgstr "PIN 码"
+
+msgid "Arrange tool"
+msgstr "排列工具"
+
+msgid "Draw a room"
+msgstr "绘制房间"
+
+msgid "Add a floor"
+msgstr "添加楼层"
+
+msgid "All floors"
+msgstr "全部楼层"
+
+msgid "Zoom in"
+msgstr "放大"
+
+msgid "Zoom out"
+msgstr "缩小"
+
+msgid "Turn left"
+msgstr "向左旋转"
+
+msgid "Turn right"
+msgstr "向右旋转"
+
+msgid "Show the whole floor"
+msgstr "显示整个楼层"
+
+msgid "Detailed models"
+msgstr "详细型号"
+
+msgid "Places on this level"
+msgstr "此层级的位置"
+
+msgid "Furniture, plants and the AC units are free models from Poly Haven (CC0), shrunk for phones. Turn off Detailed models to download none."
+msgstr "家具、绿植和空调等精细模型来自 Poly Haven (CC0),已针对手机端精简体积。关闭「精细模型」则不下载任何模型。"
+
+msgid "Map"
+msgstr "平面地图"
+
+msgid "Nothing here."
+msgstr "这里空空如也。"
+
+msgid "Show fewer"
+msgstr "收起部分"
+
+msgid "Show {0} more"
+msgstr "再显示 {0} 项"
+
+msgid "Nothing here yet."
+msgstr "这里还没有内容。"
+
+msgid "What’s in {name}"
+msgstr "{name} 中有什么"
+
+msgid "{0, plural, one {# floor} other {# floors}}"
+msgstr "{0, plural, one {# 个楼层} other {# 个楼层}}"
+
+msgid "<0>{0}0> low"
+msgstr "<0>{0}0> 库存不足"
+
+msgid "<0>{0}0> lent"
+msgstr "<0>{0}0> 项已借出"
+
+msgid "<0>{0}0> due"
+msgstr "<0>{0}0> 到期"
+
+msgid "The map lists the first {0} things; search the location for the rest."
+msgstr "平面图仅列出前 {0} 件物品;其余物品请在空间内搜索。"
+
+msgid "Find a thing or a short ID"
+msgstr "查找物品或短 ID"
+
+msgid "By room"
+msgstr "按房间"
+
+msgid "Needs attention"
+msgstr "需要注意"
+
+msgid "map"
+msgstr "平面图"
+
+msgid "all locations"
+msgstr "所有空间"
+
+msgid "{how} ({n})"
+msgstr "{how}({n})"
+
+msgid "For your whole account: set it under All locations."
+msgstr "如需应用于整个账号,请在「所有空间」下设置。"
+
+msgid "Viewers hear only about members."
+msgstr "查看者仅接收与成员相关的通知。"
+
+msgid "Not sent here."
+msgstr "此处未发送。"
+
+msgid "Paused: {name} is off here."
+msgstr "已暂停:此处已关闭 {name}。"
+
+msgid "{where} follows all locations again"
+msgstr "{where} 重新关注所有空间"
+
+msgid "{what} by {how} in {where}, set for this location only"
+msgstr "{where} 中的 {what} 按{how}(仅限此空间)"
+
+msgid "{what} by {how} in {where}"
+msgstr "{what}({how}),位于 {where}"
+
+msgid "In Kept is off, so nothing is sent."
+msgstr "「站内通知」已关闭,因此不会发送任何通知。"
+
+msgid "Due dates"
+msgstr "到期日期"
+
+msgid "Stock"
+msgstr "库存"
+
+msgid "All locations"
+msgstr "所有空间"
+
+msgid "Set for this location only"
+msgstr "仅为此空间设置"
+
+msgid "Reset this location to all locations"
+msgstr "将此空间重置为跟随「所有空间」"
+
+msgid "Add more channels"
+msgstr "添加更多渠道"
+
+msgid "Applies to every location, ones you add later too. Pick a location to change it there only."
+msgstr "应用于所有空间,包括你之后新增的空间。选择单个空间即可仅针对该空间修改。"
+
+msgid "You're a member here: Kept starts with only the loans you record."
+msgstr "你是此空间的成员:Kept 默认仅显示你记录的借出信息。"
+
+msgid "You're a viewer here: only members joining and leaving."
+msgstr "你是此空间的查看者:仅展示成员加入与离开记录。"
+
+msgid "Not sent this way"
+msgstr "未通过此方式发送"
+
+msgid "What reaches you"
+msgstr "接收哪些通知"
+
+msgid "Start the camera"
+msgstr "开启相机"
+
+msgid "Get started hidden. Help brings it back."
+msgstr "「快速开始」已隐藏,可在「帮助」中重新显示。"
+
+msgid "add 3 things"
+msgstr "添加 3 件物品"
+
+msgid "print a label"
+msgstr "打印标签"
+
+msgid "invite someone"
+msgstr "邀请成员"
+
+msgid "connect AI"
+msgstr "连接 AI"
+
+msgid "install on your phone"
+msgstr "安装到手机"
+
+msgid "Then: {after}"
+msgstr "变更后:{after}"
+
+msgid "{name}, with {person}"
+msgstr "{name},借给 {person}"
+
+msgid "{late, plural, one {# day late} other {# days late}}"
+msgstr "{late, plural, one {已逾期 # 天} other {已逾期 # 天}}"
+
+msgid "last seen {day}"
+msgstr "上次见到:{day}"
+
+msgid "{left} left, keep {keep}"
+msgstr "剩余 {left},保留 {keep}"
+
+msgid "{done} of {total} done"
+msgstr "已完成 {done} / {total}"
+
+msgid "Next: <0>{title}0>"
+msgstr "下一步:<0>{title}0>"
+
+msgid "Hide Get started for good"
+msgstr "永久隐藏「开始使用」"
+
+msgid "Spent on things, {year} so far"
+msgstr "{year} 年至今物品支出"
+
+msgid "Value of what you own"
+msgstr "名下物品总价值"
+
+msgid "{count} of {total} things have a value"
+msgstr "{count} / {total} 件物品已填写估值"
+
+msgid "Leaves out {off}: Money is off there."
+msgstr "不包含 {off}:该空间未开启财务功能。"
+
+msgid "{count} overdue"
+msgstr "{count} 项已逾期"
+
+msgid "{count} due"
+msgstr "{count} 项到期"
+
+msgid "{count} expiring"
+msgstr "{count} 项即将到期"
+
+msgid "{count} lent out"
+msgstr "已借出 {count} 件"
+
+msgid "{count} uncertain"
+msgstr "{count} 项待确认"
+
+msgid "{count} low"
+msgstr "{count} 项库存不足"
+
+msgid "No rooms"
+msgstr "暂无房间"
+
+msgid "<0>{value}0> value"
+msgstr "<0>{value}0> 估值"
+
+msgid "Photos to review"
+msgstr "待审核照片"
+
+msgid "Added"
+msgstr "已添加"
+
+msgid "Nothing yet. What you add, move and check shows here."
+msgstr "暂无动态。你添加、移动和核查的记录都会显示在这里。"
+
+msgid "Nothing added yet."
+msgstr "暂未添加任何内容。"
+
+msgid "Nothing moved yet."
+msgstr "尚未移动任何物品。"
+
+msgid "Nothing checked yet."
+msgstr "尚未清点任何物品。"
+
+msgid "Shortcuts"
+msgstr "快捷键"
+
+msgid "Type part of a name, a brand, a serial or a short ID. Each result says where it is."
+msgstr "输入名称、品牌、序列号或短 ID 的一部分。每条结果都会显示其所在位置。"
+
+msgid "Every section, one click away. A module shows here once it's on in one of your locations."
+msgstr "所有板块一键直达。某个功能模块在你的任一空间开启后,就会显示在这里。"
+
+msgid "What reaches you and how, for all your locations or one at a time."
+msgstr "设置接收哪些通知及接收方式,可统一应用到所有空间,也可逐个设置。"
+
+msgid "Done {day}"
+msgstr "完成于 {day}"
+
+msgid "A sample household in your browser. Nothing is saved."
+msgstr "运行在你浏览器中的示例家庭空间,任何更改都不会保存。"
+
+msgid "Reset"
+msgstr "重置"
+
+msgid "Off in this demo: this would open another site."
+msgstr "演示模式中已禁用:此操作将打开外部站点。"
+
+msgid "The camera is off in this demo."
+msgstr "此演示环境中已关闭相机功能。"
+
+msgid "Push is off in this demo."
+msgstr "此演示环境中已关闭推送通知。"
+
+msgid "The camera is off in this demo"
+msgstr "此演示模式下相机已关闭"
+
+msgid "In your own Kept, Capture opens the camera here. Photos you pick stay in this tab."
+msgstr "在你自己的 Kept 中,「录入」会在此直接打开相机。你选取的照片仅保留在当前标签页中。"
+
+msgid "The app lock is off in this demo."
+msgstr "此演示环境中已关闭应用锁。"
+
+msgid "Downloads are off in this demo."
+msgstr "此演示环境中已关闭下载功能。"
+
+msgid "Your own Kept makes the PDF here. This demo has no files."
+msgstr "在你自己的 Kept 中会在此直接生成 PDF。当前演示环境没有可下载的文件。"
+
+msgid "Sample answers in this demo: no AI is asked."
+msgstr "此演示中使用示例回答:不会实际请求 AI。"
+
+msgid "Paperless-ngx"
+msgstr "Paperless-ngx"
+
+msgid "Paperless"
+msgstr "Paperless"
+
+msgid "Paperless answers: version {0}"
+msgstr "Paperless 响应:版本 {0}"
+
+msgid "Paperless couldn't answer."
+msgstr "Paperless 无法响应。"
+
+msgid "Paperless disconnected"
+msgstr "已断开 Paperless 连接"
+
+msgid "Disconnect Paperless?"
+msgstr "断开 Paperless 连接?"
+
+msgid "The {links} links to its documents go too. Documents copied into Kept stay."
+msgstr "指向其文档的 {links} 条关联链接也会一并移除;已复制到 Kept 内的文档仍会保留。"
+
+msgid "Members can no longer link its documents."
+msgstr "成员将无法再关联其中的文档。"
+
+msgid "Disconnect"
+msgstr "断开连接"
+
+msgid "Not encrypted"
+msgstr "未加密"
+
+msgid "This address is plain http, so the token travels unencrypted on your network. Use https if Paperless has it."
+msgstr "该地址使用明文 HTTP,令牌在网络中不会加密传输。如果 Paperless 支持,请改用 HTTPS。"
+
+msgid "Version unknown"
+msgstr "版本未知"
+
+msgid "{0, plural, one {# linked document} other {# linked documents}}"
+msgstr "{0, plural, one {# 份关联文档} other {# 份关联文档}}"
+
+msgid "Connected by {0}, changed {1}"
+msgstr "由 {0} 连接,修改于 {1}"
+
+msgid "Paperless saved"
+msgstr "Paperless 配置已保存"
+
+msgid "Paperless connected: version {0}"
+msgstr "Paperless 已连接:版本 {0}"
+
+msgid "Change the connection"
+msgstr "更改连接"
+
+msgid "Connect Paperless-ngx"
+msgstr "连接 Paperless-ngx"
+
+msgid "Members can then link a thing or a place to its receipts, manuals and warranty cards in Paperless, without uploading them twice. Kept stores the document's number and title, not the file, unless someone copies it into Kept."
+msgstr "之后成员即可将物品或位置关联到 Paperless 中的收据、说明书和保修卡,无需重复上传。除非有人将文件复制到 Kept,否则 Kept 仅保存文档编号和标题,不存储原文件。"
+
+msgid "Paperless address"
+msgstr "Paperless 地址"
+
+msgid "The address you open Paperless at, for example https://paperless.example.com."
+msgstr "你平时访问 Paperless 的网址,例如 https://paperless.example.com。"
+
+msgid "Plain http"
+msgstr "明文 HTTP"
+
+msgid "Kept accepts http only for an address on your own network, and only when an instance admin allows private addresses. The token travels unencrypted there."
+msgstr "Kept 仅对内网地址且在实例管理员允许私有地址时才接受 HTTP 连接。在此模式下,令牌将以明文传输。"
+
+msgid "API token"
+msgstr "API 令牌"
+
+msgid "In Paperless, open My Profile and press the circular arrow by the API token. Kept sees what that user sees."
+msgstr "在 Paperless 中打开“个人资料 (My Profile)”,点击 API 令牌旁的刷新图标生成令牌。Kept 的可见范围与该用户一致。"
+
+msgid "Link from Paperless"
+msgstr "从 Paperless 关联"
+
+msgid "Paperless can't be reached"
+msgstr "无法连接到 Paperless"
+
+msgid "The titles below are as Kept last saw them."
+msgstr "以下标题为 Kept 上次读取时的记录。"
+
+msgid "Paperless documents"
+msgstr "Paperless 文档"
+
+msgid "Copied into Kept"
+msgstr "已复制到 Kept"
+
+msgid "Couldn't copy it"
+msgstr "无法复制"
+
+msgid "Unlink this document?"
+msgstr "取消关联此文档?"
+
+msgid "It comes off {name}. Paperless keeps it, and the copy in Kept stays."
+msgstr "将从 {name} 移除关联。Paperless 中的原文件及 Kept 中的副本均会保留。"
+
+msgid "It comes off {name}. Paperless keeps it."
+msgstr "它将从 {name} 上取消关联,Paperless 中仍会保留原文件。"
+
+msgid "Couldn't unlink it"
+msgstr "无法取消关联"
+
+msgid "Open in Paperless"
+msgstr "在 Paperless 中打开"
+
+msgid "Copy into Kept"
+msgstr "复制到 Kept"
+
+msgid "Unlink {0}"
+msgstr "取消关联 {0}"
+
+msgid "Linked {n} from Paperless"
+msgstr "已从 Paperless 关联 {n} 份"
+
+msgid "Link from Paperless to {name}"
+msgstr "从 Paperless 关联到 {name}"
+
+msgid "Search Paperless"
+msgstr "搜索 Paperless"
+
+msgid "Words from the title or the text, a correspondent, a type or a tag."
+msgstr "标题或正文中的关键词、往来方、类型或分类标签。"
+
+msgid "Searching Paperless"
+msgstr "正在搜索 Paperless"
+
+msgid "No documents found"
+msgstr "未找到文档"
+
+msgid "Try other words."
+msgstr "请尝试其他关键词。"
+
+msgid "This Paperless has no documents yet."
+msgstr "此 Paperless 中还没有任何文档。"
+
+msgid "Page {page} of {pages}"
+msgstr "第 {page} 页,共 {pages} 页"
+
+msgid "{0, plural, =0 {Link} one {Link # document} other {Link # documents}}"
+msgstr "{0, plural, =0 {关联} one {关联 # 份文档} other {关联 # 份文档}}"
+
+msgid "Use https:// for a Paperless outside your network. Over http the token would travel unencrypted."
+msgstr "连接外网 Paperless 时请使用 https://,通过 http 传输令牌将不加密。"
+
+msgid "Kept couldn't reach Paperless at that address."
+msgstr "Kept 无法通过该地址连接到 Paperless。"
+
+msgid "Paperless didn't answer within 10 seconds."
+msgstr "Paperless 未在 10 秒内响应。"
+
+msgid "That address answered with a redirect. Use the address it leads to."
+msgstr "该地址返回了重定向响应,请直接使用目标地址。"
+
+msgid "Paperless refused the token."
+msgstr "Paperless 拒绝了该令牌。"
+
+msgid "That address doesn't answer like Paperless-ngx."
+msgstr "该地址的响应格式不符合 Paperless-ngx。"
+
+msgid "Kept needs Paperless-ngx 2.16 or later."
+msgstr "Kept 需要 Paperless-ngx 2.16 或更高版本。"
+
+msgid "Paperless no longer has this document, or the token's user can't see it."
+msgstr "Paperless 中已不存在此文档,或当前令牌所属用户无权查看。"
+
+msgid "That document is larger than Kept takes."
+msgstr "该文档超过了 Kept 允许的最大体积。"
+
+msgid "Paperless connected"
+msgstr "已连接 Paperless"
+
+msgid "Paperless connection changed"
+msgstr "Paperless 连接设置已更改"
+
+msgid "Paperless document linked"
+msgstr "已关联 Paperless 文档"
+
+msgid "Paperless document unlinked"
+msgstr "已取消关联 Paperless 文档"
+
+msgid "Paperless document copied into Kept"
+msgstr "已将 Paperless 文档复制到 Kept"
+
+msgid "Small device"
+msgstr "小型设备"
+
+msgid "Furniture"
+msgstr "家具"
+
+msgid "Storage"
+msgstr "存储"
+
+msgid "Electronics"
+msgstr "电子产品"
+
+msgid "Kitchen and laundry"
+msgstr "厨房与洗衣"
+
+msgid "Plants and outdoor"
+msgstr "绿植与户外"
+
+msgid "Stairs and areas"
+msgstr "楼梯与区域"
+
+msgid "Shape: {shape}, from its type"
+msgstr "形状:{shape}(继承自类型)"
+
+msgid "Shape: {shape}, from its name"
+msgstr "形状:{shape}(根据名称推断)"
+
+msgid "Shape: {shape}, a guess"
+msgstr "形状:{shape}(推测)"
+
+msgid "Shape: {shape}"
+msgstr "形状:{shape}"
+
+msgid "Pick a shape"
+msgstr "选择形状"
+
+msgid "Shape for {name}"
+msgstr "{name} 的形状"
+
+msgid "Find a shape"
+msgstr "查找模型形状"
+
+msgid "Find a shape: TV, shelf, box…"
+msgstr "搜索形状:电视、货架、箱子…"
+
+msgid "Shapes"
+msgstr "形状"
+
+msgid "No shape matches “{query}”. Try Small thing or Small device, and give it a name that says what it is."
+msgstr "没有与“{query}”匹配的形状。可尝试「小物件」或「小型设备」,并填写能说明其用途的名称。"
+
+msgid "Table"
+msgstr "表格"
+
+msgid "table"
+msgstr "表格"
+
+msgid "{count, plural, one {Move # thing} other {Move # things}}"
+msgstr "{count, plural, one {移动 # 件物品} other {移动 # 件物品}}"
+
+msgid "The move waits with your other changes until you save. To move to another location, use Move on the list."
+msgstr "移动操作会与其他修改一同保留,直到你点击保存。如需移至其他空间,请在列表中使用“移动”。"
+
+msgid "{count, plural, one {Tags of # thing} other {Tags of # things}}"
+msgstr "{count, plural, one {# 件物品的分类标签} other {# 件物品的分类标签}}"
+
+msgid "Add or remove"
+msgstr "增减"
+
+msgid "Add tags"
+msgstr "添加分类标签"
+
+msgid "Remove tags"
+msgstr "移除分类标签"
+
+msgid "{count, plural, one {Set a field on # thing} other {Set a field on # things}}"
+msgstr "{count, plural, one {为 # 件物品设置字段} other {为 # 件物品设置字段}}"
+
+msgid "Leave it empty to clear it."
+msgstr "留空即可清除。"
+
+msgid "{count, plural, one {Send # thing to the Trash?} other {Send # things to the Trash?}}"
+msgstr "{count, plural, one {将 # 件物品移入回收站?} other {将 # 件物品移入回收站?}}"
+
+msgid "Some of them hold things"
+msgstr "其中部分包含物品"
+
+msgid "Move what's inside out, to where each one is"
+msgstr "将内部物品移出至其各自所在位置"
+
+msgid "Trash what's inside too"
+msgstr "连同内部物品一起移入回收站"
+
+msgid "They stay in the Trash for 30 days. Undo brings them all back."
+msgstr "它们会在回收站中保留 30 天。点击撤销可全部恢复。"
+
+msgid "Send to Trash"
+msgstr "移入回收站"
+
+msgid "Short ID"
+msgstr "短 ID"
+
+msgid "Warranty ends"
+msgstr "保修到期日"
+
+msgid "This one is counted one by one: its quantity stays 1."
+msgstr "此物品按单件管理:数量始终保持为 1。"
+
+msgid "A box"
+msgstr "收纳箱"
+
+msgid "{0, plural, one {Fix # row before saving} other {Fix # rows before saving}}"
+msgstr "{0, plural, one {保存前请先修正 # 行} other {保存前请先修正 # 行}}"
+
+msgid "{cells, plural, one {Saved # change} other {Saved # changes}}"
+msgstr "{cells, plural, one {已保存 # 处更改} other {已保存 # 处更改}}"
+
+msgid "{0, plural, one {# row wasn't saved} other {# rows weren't saved}}"
+msgstr "{0, plural, one {有 # 行未保存} other {有 # 行未保存}}"
+
+msgid "{0, plural, one {Discard # change?} other {Discard # changes?}}"
+msgstr "{0, plural, one {放弃这 # 项更改?} other {放弃这 # 项更改?}}"
+
+msgid "Leave without saving?"
+msgstr "确定不保存并离开吗?"
+
+msgid "{0, plural, one {# change isn't saved yet.} other {# changes aren't saved yet.}}"
+msgstr "{0, plural, one {尚有 # 项更改未保存。} other {尚有 # 项更改未保存。}}"
+
+msgid "Leave"
+msgstr "退出"
+
+msgid "Stay"
+msgstr "留在此页"
+
+msgid "{0, plural, one {Sent # thing to the Trash} other {Sent # things to the Trash}}"
+msgstr "{0, plural, one {已将 # 件物品移入回收站} other {已将 # 件物品移入回收站}}"
+
+msgid "Not saved: {0}"
+msgstr "未保存:{0}"
+
+msgid "Tags…"
+msgstr "分类标签…"
+
+msgid "Set a field…"
+msgstr "设置字段…"
+
+msgid "Send at most 200 to the Trash at a time."
+msgstr "每次最多只能将 200 项移入回收站。"
+
+msgid "Select none"
+msgstr "全不选"
+
+msgid "Select all"
+msgstr "全选"
+
+msgid "Changes"
+msgstr "变更记录"
+
+msgid "{0, plural, one {# change} other {# changes}}"
+msgstr "{0, plural, one {# 项更改} other {# 项更改}}"
+
+msgid "{0, plural, one {on # thing} other {on # things}}"
+msgstr "{0, plural, one {位于 # 件物品上} other {位于 # 件物品上}}"
+
+msgid "{0, plural, one {# row needs a fix} other {# rows need a fix}}"
+msgstr "{0, plural, one {# 行需要修正} other {# 行需要修正}}"
+
+msgid "{0, plural, one {Save # change} other {Save # changes}}"
+msgstr "{0, plural, one {保存 # 项更改} other {保存 # 项更改}}"
+
+msgid "{who} changed this since you opened it."
+msgstr "{who} 在你打开此页面后修改了此内容。"
+
+msgid "Someone changed this since you opened it."
+msgstr "自你打开后,有人修改了此内容。"
+
+msgid "You can view this location but not change it."
+msgstr "你可以查看此空间,但无法修改。"
+
+msgid "It's no longer here."
+msgstr "它已不在这里。"
+
+msgid "Check the highlighted cells."
+msgstr "请检查高亮显示的单元格。"
+
+msgid "Moving"
+msgstr "正在移动"
+
+msgid "Scan to unpack"
+msgstr "扫码拆箱"
+
+msgid "Point at a box's label, or the code on its contents sheet."
+msgstr "对准收纳箱标签,或装箱清单上的二维码。"
+
+msgid "Not a box of this move"
+msgstr "不属于本次搬家的箱子"
+
+msgid "{title} taken out of the move. The box stays where it is."
+msgstr "已将 {title} 移出搬家清单,箱子仍在原位。"
+
+msgid "Since {when}, by <0>{by}0>"
+msgstr "自 {when} 起,由 <0>{by}0>"
+
+msgid "Since {when}"
+msgstr "自 {when} 起"
+
+msgid "Goes to"
+msgstr "将移至"
+
+msgid "No room chosen yet"
+msgstr "尚未选择房间"
+
+msgid "Choose"
+msgstr "选择"
+
+msgid "Now in <0>{0}0>"
+msgstr "现位于 <0>{0}0>"
+
+msgid "It was unpacked into a location you can't see."
+msgstr "它已被拆箱放入你无权查看的空间中。"
+
+msgid "Unpack"
+msgstr "拆箱"
+
+msgid "Mark in transit"
+msgstr "标为运输中"
+
+msgid "Back to packed"
+msgstr "恢复为已打包"
+
+msgid "{0, plural, one {Inside: # thing} other {Inside: # things}}"
+msgstr "{0, plural, one {内部:# 件物品} other {内部:# 件物品}}"
+
+msgid "Loading what's inside"
+msgstr "正在加载内部物品"
+
+msgid "Nothing in it yet"
+msgstr "里面暂无物品"
+
+msgid "Open the box to add things here, or pack with the scanner."
+msgstr "打开箱子在此添加物品,或用扫码功能打包。"
+
+msgid "{0, plural, one {Holds # thing} other {Holds # things}}"
+msgstr "{0, plural, one {内含 # 件物品} other {内含 # 件物品}}"
+
+msgid "As this phone last saw it."
+msgstr "此手机上次同步时的状态。"
+
+msgid "Open the box"
+msgstr "打开箱子"
+
+msgid "Pack with the scanner"
+msgstr "使用扫码器装箱"
+
+msgid "Contents sheet"
+msgstr "装箱清单"
+
+msgid "Take {title} out of the move?"
+msgstr "将 {title} 移出本次搬家?"
+
+msgid "The box and what's in it stay where they are."
+msgstr "箱子及其中的物品将保留在原处。"
+
+msgid "Take it out"
+msgstr "取出"
+
+msgid "Take it out of the move"
+msgstr "移出搬家清单"
+
+msgid "Unpack {title}"
+msgstr "拆箱:{title}"
+
+msgid "Room it goes to"
+msgstr "目标房间"
+
+msgid "{name} unpacked into {where}"
+msgstr "{name} 已拆箱至 {where}"
+
+msgid "{name}: {0}"
+msgstr "{name}:{0}"
+
+msgid "Everything in the box goes with it."
+msgstr "箱内的所有物品会一并移动。"
+
+msgid "Unpack into {where}"
+msgstr "拆箱放入 {where}"
+
+msgid "Choose a room"
+msgstr "选择房间"
+
+msgid "Packed"
+msgstr "已装箱"
+
+msgid "In transit"
+msgstr "运输中"
+
+msgid "Unpacked"
+msgstr "已拆箱"
+
+msgid "In progress"
+msgstr "进行中"
+
+msgid "Box {number}"
+msgstr "{number} 号箱"
+
+msgid "Loading the move"
+msgstr "正在加载搬家记录"
+
+msgid "Open this move once with a connection, and it is on this phone after that."
+msgstr "在联网状态下打开一次此搬家任务,之后即可在此手机上离线查看。"
+
+msgid "Every box is unpacked"
+msgstr "所有箱子均已拆完"
+
+msgid "Mark the move done when you're settled in."
+msgstr "安顿好后即可将此搬家标记为已完成。"
+
+msgid "{0, plural, one {# box still to unpack} other {# boxes still to unpack}}"
+msgstr "{0, plural, one {还有 # 个收纳箱待拆箱} other {还有 # 个收纳箱待拆箱}}"
+
+msgid "Goes to <0>{0}0>"
+msgstr "去往 <0>{0}0>"
+
+msgid "In a location you can't see"
+msgstr "位于你无权查看的空间中"
+
+msgid "Move deleted. Its boxes stay where they are."
+msgstr "搬家记录已删除,箱子仍留在原位。"
+
+msgid "As of {asOf}. Changes you make wait on this phone and sync when you're online."
+msgstr "数据截至 {asOf}。你所做的更改会暂存在此手机上,联网后自动同步。"
+
+msgid "This move is marked done. Open it again to change its boxes."
+msgstr "此搬家已标记为完成。重新打开后即可修改其中的箱子。"
+
+msgid "Add a box"
+msgstr "添加箱子"
+
+msgid "Contents sheets"
+msgstr "物品清单表"
+
+msgid "Mark every packed box in transit?"
+msgstr "将所有已装箱的箱子标记为运输中?"
+
+msgid "{0, plural, one {# box is going in the van.} other {# boxes are going in the van.}}"
+msgstr "{0, plural, one {# 个箱子将装车。} other {# 个箱子将装车。}}"
+
+msgid "Mark all in transit"
+msgstr "全部标记为运输中"
+
+msgid "Search boxes"
+msgstr "搜索箱子"
+
+msgid "Number, name or room"
+msgstr "编号、名称或房间"
+
+msgid "by room"
+msgstr "按房间"
+
+msgid "No boxes yet"
+msgstr "暂无箱子"
+
+msgid "Each box gets a number. Print its label, pack it, and scan it at the other end."
+msgstr "每个箱子都会分配一个编号。打印标签并贴好、装箱,到达目的地后扫码即可。"
+
+msgid "Mark the move done"
+msgstr "标记搬家已完成"
+
+msgid "Open it again"
+msgstr "重新打开"
+
+msgid "Delete this move?"
+msgstr "删除此次搬家记录?"
+
+msgid "The boxes and everything in them stay where they are; only their numbers and states go."
+msgstr "箱子及箱内物品都保留在原位;仅移除它们的搬家编号和状态。"
+
+msgid "Delete the move"
+msgstr "删除搬家记录"
+
+msgid "{name} added"
+msgstr "已添加 {name}"
+
+msgid "{0, plural, one {# box} other {# boxes}}"
+msgstr "{0, plural, one {# 个箱子} other {# 个箱子}}"
+
+msgid "Start a move"
+msgstr "开始搬家"
+
+msgid "Offline: these are the moves this phone has opened."
+msgstr "离线状态:仅显示此手机已打开过的搬家记录。"
+
+msgid "Moves"
+msgstr "搬家"
+
+msgid "Search moves"
+msgstr "搜索搬家记录"
+
+msgid "Name or location"
+msgstr "名称或空间"
+
+msgid "Started"
+msgstr "已开始"
+
+msgid "by status"
+msgstr "按状态"
+
+msgid "No moves yet"
+msgstr "暂无搬家记录"
+
+msgid "Moving house? Pack into numbered boxes, print a label and a contents sheet for each, and scan a box at the other end to unpack it into its room."
+msgstr "要搬家?将物品装入编号箱中,为每个箱子打印标签和装箱清单,到达新家后扫码即可将物品拆箱放入对应房间。"
+
+msgid "Give the move a name."
+msgstr "请为此次搬家命名。"
+
+msgid "To the new house"
+msgstr "搬往新家"
+
+msgid "Packing up"
+msgstr "正在装箱"
+
+msgid "Going to"
+msgstr "前往位置"
+
+msgid "Rooms of {fromName}"
+msgstr "{fromName} 的房间"
+
+msgid "Moving to a new home? Add it as a location first, so each box can be unpacked into its rooms."
+msgstr "正在搬入新家吗?请先将其添加为一个新空间,这样每个箱子都能直接拆箱放进对应的房间。"
+
+msgid "This location has no rooms yet."
+msgstr "此空间暂无房间。"
+
+msgid "It gets the next number. Put things in it from its page, or with the scanner."
+msgstr "它将自动获取下一个编号。你可以在其详情页或使用扫码功能向箱内添加物品。"
+
+msgid "Room it goes to (optional)"
+msgstr "目标房间(可选)"
+
+msgid "Add the box"
+msgstr "添加箱子"
+
+msgid "A page per box: its number, the room it goes to, what's inside and its code. Tape it to the box; scanning the code opens the box in Kept."
+msgstr "每个箱子单独一页:包含箱号、目标房间、箱内物品和二维码。贴在箱子上后,扫码即可在 Kept 中打开该箱。"
+
+msgid "Add a box first."
+msgstr "请先添加一个箱子。"
+
+msgid "Already unpacked into <0>{0}0>."
+msgstr "已拆箱放入 <0>{0}0>。"
+
+msgid "Already unpacked."
+msgstr "已拆箱。"
+
+msgid "Scan another box"
+msgstr "扫描下一个箱子"
+
+msgid "Move started"
+msgstr "搬家已开始"
+
+msgid "Move changed"
+msgstr "搬家计划已更改"
+
+msgid "Move deleted"
+msgstr "已删除搬家记录"
+
+msgid "Added to a move as a box"
+msgstr "已作为箱子添加到搬家"
+
+msgid "Moving box changed"
+msgstr "搬家箱已更改"
+
+msgid "Box unpacked"
+msgstr "箱子已拆箱"
+
+msgid "Taken out of a move"
+msgstr "已从搬家中移出"
+
+msgid "Desktop PC"
+msgstr "台式电脑"
+
+msgid "Keyboard"
+msgstr "键盘"
+
+msgid "Mouse"
+msgstr "鼠标"
+
+msgid "Webcam"
+msgstr "网络摄像头"
+
+msgid "Desk speaker"
+msgstr "桌面音箱"
+
+msgid "Tall speaker"
+msgstr "落地音箱"
+
+msgid "Smart speaker"
+msgstr "智能音箱"
+
+msgid "Soundbar"
+msgstr "条形音箱"
+
+msgid "Headphones"
+msgstr "头戴式耳机"
+
+msgid "Router"
+msgstr "路由器"
+
+msgid "Printer"
+msgstr "打印机"
+
+msgid "Game console"
+msgstr "游戏机"
+
+msgid "Game controller"
+msgstr "游戏手柄"
+
+msgid "Tablet"
+msgstr "平板电脑"
+
+msgid "Power strip"
+msgstr "插线板"
+
+msgid "External drive"
+msgstr "外接硬盘"
+
+msgid "Large"
+msgstr "大"
+
+msgid "Things · <0>{thingCount}0>"
+msgstr "物品 · <0>{thingCount}0>"
+
+msgid "Things here · <0>{thingCount}0>"
+msgstr "此处物品 · <0>{thingCount}0>"
+
+msgid "Put on…"
+msgstr "放置于…"
+
+msgid "Add on it"
+msgstr "继续在其上添加"
+
+msgid "Monitor arm"
+msgstr "显示器支架"
+
+msgid "Dual monitor arm"
+msgstr "双屏显示器支架"
+
+msgid "Portable speaker"
+msgstr "便携音箱"
+
+msgid "Boombox"
+msgstr "手提音响"
+
+msgid "Headset"
+msgstr "头戴式耳机"
+
+msgid "Earbuds"
+msgstr "入耳式耳机"
+
+msgid "{shape} · on {on}"
+msgstr "{shape} · {on}"
+
+msgid "Put {0} on…"
+msgstr "将 {0} 放置于…"
+
+msgid "On {0}"
+msgstr "于 {0}"
+
+msgid "Take off"
+msgstr "取下"
+
+msgid "Find a place to put it"
+msgstr "为它找一个存放位置"
+
+msgid "Find in {roomName}"
+msgstr "在 {roomName} 中查找"
+
+msgid "What can carry it"
+msgstr "可装入此物品的容器"
+
+msgid "Nothing else in {roomName} can carry it."
+msgstr "{roomName} 中没有其他位置可以放置它。"
+
+msgid "Nothing in {roomName} can carry it. Put a desk, a shelf or a monitor on the map first."
+msgstr "{roomName} 中没有可摆放它的载体。请先在地图上放置书桌、货架或显示器。"
+
+msgid "Add on {0}"
+msgstr "添加于 {0}"
+
+msgid "{max, plural, one {Full: it holds one monitor.} other {Full: it holds # monitors.}}"
+msgstr "{max, plural, one {已满:可容纳 1 台显示器。} other {已满:可容纳 # 台显示器。}}"
+
+msgid "{left, plural, one {Room for one more.} other {Room for # more.}}"
+msgstr "{left, plural, one {还能再添 1 项。} other {还能再添 # 项。}}"
+
+msgid "Find a thing to add"
+msgstr "查找要添加的物品"
+
+msgid "Things to add on it"
+msgstr "待添加到其中的物品"
+
+msgid "{n, plural, one {Put # on it} other {Put # on it}}"
+msgstr "{n, plural, one {将 # 项放入其中} other {将 # 项放入其中}}"
+
+msgid "Pick what goes on it"
+msgstr "选择要打印在上面的内容"
+
+msgid "On it now: {onNow}"
+msgstr "当前占用:{onNow}"
+
+msgid "Added a photo to {name}"
+msgstr "已向 {name} 添加照片"
+
+msgid "Captured {name} from a photo"
+msgstr "通过照片录入了 {name}"
+
+msgid "Logged a reading of {name} from a photo"
+msgstr "已从照片中记录 {name} 的读数"
+
+msgid "Filled in {name} from a photo"
+msgstr "已从照片自动填写 {name}"
+
+msgid "Read the photo of {name} again"
+msgstr "重新识别 {name} 的照片"
+
+msgid "Merged a duplicate into {name}"
+msgstr "已将重复项合并到 {name}"
+
+msgid "Arranged the map"
+msgstr "已整理地图布局"
+
+msgid "Checked what is in {name}"
+msgstr "已核对 {name} 内的物品"
+
+msgid "Gave {name} a label"
+msgstr "已为 {name} 分配标签"
+
+msgid "Changed how {name} numbers its codes"
+msgstr "已更改 {name} 的编码编号规则"
+
+msgid "Handed {name} to a new owner"
+msgstr "已将 {name} 移交给新所有者"
+
+msgid "Made an inventory report of {name}"
+msgstr "已生成 {name} 的资产清单报告"
+
+msgid "Made an insurance report for {name}"
+msgstr "为 {name} 生成了保险报告"
+
+msgid "Made a vehicle history report for {name}"
+msgstr "已为 {name} 生成车辆历史报告"
+
+msgid "Cancelled the account deletion"
+msgstr "已取消注销账号"
+
+msgid "Asked to delete the account"
+msgstr "已申请删除账号"
+
+msgid "Changed the account email"
+msgstr "已更改账户邮箱"
+
+msgid "Reset a password from the command line"
+msgstr "通过命令行重置密码"
+
+msgid "Turned off an account from the command line"
+msgstr "通过命令行停用了一个账号"
+
+msgid "Turned an account back on from the command line"
+msgstr "已通过命令行重新启用一个账号"
+
+msgid "Turned off a currency"
+msgstr "停用了一个币种"
+
+msgid "Turned on a currency"
+msgstr "已启用一种货币"
+
+msgid "Made someone an instance admin"
+msgstr "已将某位用户设为实例管理员"
+
+msgid "Removed an instance admin"
+msgstr "已移除一位实例管理员"
+
+msgid "Discarded a failed job"
+msgstr "已丢弃一个失败的任务"
+
+msgid "Retried a failed job"
+msgstr "已重试失败的任务"
+
+msgid "Turned off an account"
+msgstr "停用了一个账号"
+
+msgid "Turned an account back on"
+msgstr "重新启用了一个账号"
+
+msgid "Reset someone’s two-step sign-in"
+msgstr "重置成员的双重验证登录"
+
+msgid "Signed someone out everywhere"
+msgstr "已将某用户从所有设备退出登录"
+
+msgid "Removed the AI spending cap"
+msgstr "已移除 AI 费用上限"
+
+msgid "Set the AI spending cap"
+msgstr "设置 AI 消费上限"
+
+msgid "Paused AI"
+msgstr "已暂停 AI"
+
+msgid "Resumed AI"
+msgstr "已恢复 AI"
+
+msgid "Looked up AI prices"
+msgstr "已查询 AI 价格"
+
+msgid "Worked out AI costs again with new prices"
+msgstr "已按新价格重新计算 AI 费用"
+
+msgid "Removed an AI price"
+msgstr "移除了一个 AI 价格"
+
+msgid "Set an AI price"
+msgstr "设置 AI 单价"
+
+msgid "Listed an AI provider’s models"
+msgstr "已列出 AI 服务商的模型"
+
+msgid "Removed an AI provider"
+msgstr "已移除一个 AI 提供商"
+
+msgid "Set up an AI provider"
+msgstr "配置 AI 服务商"
+
+msgid "Tested an AI provider"
+msgstr "已测试一个 AI 服务商"
+
+msgid "Exported AI usage"
+msgstr "已导出 AI 用量"
+
+msgid "Google sign-in settings changed"
+msgstr "已更改 Google 登录设置"
+
+msgid "Set a managed account’s password"
+msgstr "设置托管账号的密码"
+
+msgid "Made a reset code for a managed account"
+msgstr "已为托管账号生成重置码"
+
+msgid "Changed notification settings"
+msgstr "已更改通知设置"
+
+msgid "Changed which notifications arrive"
+msgstr "更改了接收的通知类型"
+
+msgid "Changed preferences"
+msgstr "已更改偏好设置"
+
+msgid "Signed out a session"
+msgstr "已退出一个会话"
+
+msgid "Turned down an app’s request to connect"
+msgstr "已拒绝一个应用的连接请求"
+
+msgid "Let an app connect"
+msgstr "允许应用连接"
+
+msgid "Made an access token"
+msgstr "创建了一个访问令牌"
+
+msgid "Revoked an access token"
+msgstr "已撤销访问令牌"
+
+msgid "Changed an access token"
+msgstr "更改了访问令牌"
+
+msgid "Turned on notifications on a device"
+msgstr "已在一台设备上开启通知"
+
+msgid "Turned off notifications on a device"
+msgstr "已关闭某台设备的通知"
+
+msgid "Changed notifications on a device"
+msgstr "已更改某台设备的通知设置"
+
+msgid "Dismissed a tip"
+msgstr "已忽略一条提示"
+
+msgid "Brought back a tip"
+msgstr "恢复了一条提示"
+
+msgid "Read a tip"
+msgstr "查看提示"
+
+msgid "Changed how a list shows"
+msgstr "更改了列表显示方式"
+
+msgid "Removed a member"
+msgstr "已移除一名成员"
+
+msgid "Changed when guest access ends"
+msgstr "更改了访客权限的到期时间"
+
+msgid "Told the owner about a new guest"
+msgstr "已向所有者发送新访客通知"
+
+msgid "Set up the mailbox"
+msgstr "设置收件邮箱"
+
+msgid "Changed the mailbox"
+msgstr "已更改收件邮箱"
+
+msgid "Removed the mailbox"
+msgstr "已移除该邮箱"
+
+msgid "Added a notification channel"
+msgstr "已添加通知渠道"
+
+msgid "Removed a notification channel"
+msgstr "移除了一个通知渠道"
+
+msgid "Made a calendar feed"
+msgstr "已生成日历订阅源"
+
+msgid "Revoked a calendar feed"
+msgstr "已撤销一个日历订阅源"
+
+msgid "Undid a capture"
+msgstr "已撤销一次采集"
+
+msgid "Discarded a draft"
+msgstr "已丢弃一份草稿"
+
+msgid "Dealt with an inbox item"
+msgstr "处理了一条收件箱项目"
+
+msgid "Brought back an inbox item"
+msgstr "已恢复一条收件箱项目"
+
+msgid "Changed several inbox items at once"
+msgstr "已批量修改收件箱项目"
+
+msgid "Printed labels"
+msgstr "已打印的标签"
+
+msgid "Captured a receipt"
+msgstr "已采集收据"
+
+msgid "Confirmed a receipt"
+msgstr "确认了一张收据"
+
+msgid "Read a receipt"
+msgstr "读取收据"
+
+msgid "Read a meter from a photo"
+msgstr "从照片识别表计读数"
+
+msgid "Cropped a photo"
+msgstr "裁剪了一张照片"
+
+msgid "Changed the photo shown"
+msgstr "更改了展示照片"
+
+msgid "Added a template"
+msgstr "已添加模板"
+
+msgid "Changed a template"
+msgstr "修改了模板"
+
+msgid "Deleted a template"
+msgstr "已删除模板"
+
+msgid "Changed a claim’s status"
+msgstr "更改了理赔状态"
+
+msgid "Made a claim pack"
+msgstr "已生成理赔资料包"
+
+msgid "Shared a claim pack link"
+msgstr "分享了理赔材料包链接"
+
+msgid "Revoked a claim pack link"
+msgstr "已撤销一个理赔资料包链接"
+
+msgid "Started a condition report"
+msgstr "已发起一份成色与状态报告"
+
+msgid "Changed a condition report"
+msgstr "修改了状况报告"
+
+msgid "Finished a condition report"
+msgstr "已完成一份成色与状态报告"
+
+msgid "Deleted a condition report"
+msgstr "已删除状况报告"
+
+msgid "Added a room to a condition report"
+msgstr "已将房间添加到状况报告"
+
+msgid "Changed a room in a condition report"
+msgstr "更改了状况报告中的房间"
+
+msgid "Removed a room from a condition report"
+msgstr "从状态报告中移除了一个房间"
+
+msgid "Started an export"
+msgstr "已开始导出"
+
+msgid "Cancelled an export"
+msgstr "已取消导出"
+
+msgid "Downloaded an export"
+msgstr "下载了导出文件"
+
+msgid "Put secrets in an export"
+msgstr "在导出中包含密钥等敏感信息"
+
+msgid "Uploaded a file to import"
+msgstr "已上传待导入文件"
+
+msgid "Uploaded an archive to import"
+msgstr "已上传待导入的压缩包"
+
+msgid "Opened an archive to import"
+msgstr "已打开待导入的压缩包"
+
+msgid "Entered an import’s passphrase"
+msgstr "输入了导入文件的密码"
+
+msgid "Chose where an import goes"
+msgstr "已选择导入目标位置"
+
+msgid "Changed an import’s choices"
+msgstr "已更改导入选项"
+
+msgid "Checked an import"
+msgstr "检查了一项导入"
+
+msgid "Started an import"
+msgstr "已开始导入"
+
+msgid "Ran an import"
+msgstr "执行了导入"
+
+msgid "Cancelled an import"
+msgstr "取消了一次导入"
+
+msgid "Exported a report as a CSV"
+msgstr "已将报告导出为 CSV"
+
+msgid "Scheduled a report"
+msgstr "已设置定期报告"
+
+msgid "Stopped a scheduled report"
+msgstr "已停用一个定时报告"
+
+msgid "Made a condition report for {name}"
+msgstr "已为 {name} 生成状况报告"
+
+msgid "Made a moving report for {name}"
+msgstr "已为 {name} 生成搬家报告"
+
+msgid "{count, plural, one {Made # blank label} other {Made # blank labels}}"
+msgstr "{count, plural, one {已生成 # 个空白标签} other {已生成 # 个空白标签}}"
+
+msgid "{count, plural, one {Made labels for # thing} other {Made labels for # things}}"
+msgstr "{count, plural, one {已为 # 件物品制作标签} other {已为 # 件物品制作标签}}"
+
+msgid "{count, plural, one {Made labels for # place} other {Made labels for # places}}"
+msgstr "{count, plural, one {已为 # 个位置生成标签} other {已为 # 个位置生成标签}}"
+
+msgid "{count, plural, one {Arranged the map: # change} other {Arranged the map: # changes}}"
+msgstr "{count, plural, one {已整理地图:# 处更改} other {已整理地图:# 处更改}}"
+
+msgid "{count, plural, one {# thing} other {# things}}"
+msgstr "{count, plural, one {# 件物品} other {# 件物品}}"
+
+msgid "{count, plural, one {With # thing inside} other {With # things inside}}"
+msgstr "{count, plural, one {内含 # 件物品} other {内含 # 件物品}}"
+
+msgid "{count, plural, one {# thing taken out first} other {# things taken out first}}"
+msgstr "{count, plural, one {已先取出 # 件物品} other {已先取出 # 件物品}}"
+
+msgid "With photos"
+msgstr "有照片"
+
+msgid "Put {name} on the map in {room}"
+msgstr "将 {name} 放置到 {room} 的平面图上"
+
+msgid "Put {name} on the map"
+msgstr "将 {name} 放到平面图上"
+
+msgid "Took {name} off the map"
+msgstr "已将 {name} 从地图上移除"
+
+msgid "Put {name} on {host}"
+msgstr "已将 {name} 放到 {host} 上"
+
+msgid "Took {name} off {host}"
+msgstr "已将 {name} 从 {host} 取下"
+
+msgid "Turned {name}"
+msgstr "已切换 {name}"
+
+msgid "Changed the shape of {name}: {from} → {to}"
+msgstr "已修改 {name} 的形状:{from} → {to}"
+
+msgid "Resized {name}"
+msgstr "已调整 {name} 的尺寸"
+
+msgid "Changed the kind of {name}: {from} → {to}"
+msgstr "已将 {name} 的类型从 {from} 更改为 {to}"
+
+msgid "Changed the floor of {name}: {from} → {to}"
+msgstr "更改了 {name} 的楼层:{from} → {to}"
+
+msgid "Show the changes"
+msgstr "查看更改"
+
+msgid "Hide the changes"
+msgstr "隐藏变更"
+
+msgid "Hide"
+msgstr "隐藏"
+
+msgid "Email isn't set up on this server."
+msgstr "此服务器未配置邮件服务。"
+
+msgid "Ask the owner to set up email."
+msgstr "请联系管理员配置邮件服务。"
+
+msgid "Add an email address to your account."
+msgstr "为你的账号添加电子邮箱。"
+
+msgid "On the map"
+msgstr "在平面图上"
+
+msgid "Not on the map yet"
+msgstr "尚未添加到地图"
+
+msgid "No monitor in {roomName} is free."
+msgstr "{roomName} 中没有空闲的显示器。"
+
+msgid "Everything small in {roomName} is on something already."
+msgstr "{roomName} 中的所有小件物品都已摆放到承托家具上。"
+
+msgid "{name} goes to {where}"
+msgstr "{name} 将移至 {where}"
+
+msgid "It has already synced. Choose the room again."
+msgstr "该数据已同步。请重新选择房间。"
+
+msgid "Wall TV"
+msgstr "壁挂电视"
+
+msgid "Wall shelf"
+msgstr "墙面置物架"
+
+msgid "Wall cabinet"
+msgstr "壁挂柜"
+
+msgid "Picture or mirror"
+msgstr "挂画或镜子"
+
+msgid "Wall clock"
+msgstr "挂钟"
+
+msgid "Hooks"
+msgstr "Webhook 钩子"
+
+msgid "On the wall"
+msgstr "墙上"
+
+msgid "Height"
+msgstr "高度"
+
+msgid "Cubes across"
+msgstr "横向格数"
+
+msgid "Cubes up"
+msgstr "纵深格数"
+
+msgid "Turn on its side"
+msgstr "横放"
+
+msgid "Width"
+msgstr "宽度"
+
+msgid "Depth"
+msgstr "深度"
+
+msgid "Levels"
+msgstr "层级"
+
+msgid "Lower"
+msgstr "调低"
+
+msgid "Higher"
+msgstr "升高视角"
+
+msgid "From the floor to its middle"
+msgstr "从地面到其中点"
+
+msgid "On the wall, {hangs} m up"
+msgstr "挂在墙上,离地 {hangs} 米"
+
+msgid "<0>{place}0> isn’t drawn on the map. It’s in <1>{holder}1>."
+msgstr "<0>{place}0> 未绘制在平面图上,它位于 <1>{holder}1> 内。"
+
+msgid "<0>{place}0> isn’t on the map"
+msgstr "<0>{place}0> 尚未标注在平面图上"
+
+msgid "<0>{room}0> isn’t on a floor yet. Move it into a floor to put it on one."
+msgstr "<0>{room}0> 尚未归属任何楼层。将其移入楼层即可摆放到对应平面图上。"
+
+msgid "Open the map of <0>{name}0>"
+msgstr "打开 <0>{name}0> 的平面图"
+
+msgid "The map draws a location’s floors, the rooms on them and what stands in each room."
+msgstr "平面图会绘制空间的楼层、各楼层的房间,以及每个房间里放置的物件。"
+
+msgid "{steps, plural, one {# step} other {# steps}}"
+msgstr "{steps, plural, one {# 步} other {# 步}}"
+
+msgid "3D or plan"
+msgstr "3D 或平面图"
+
+msgid "Add a box and print its label. Scan it at the other end to unpack."
+msgstr "添加收纳箱并打印标签,到达目的地后扫码即可拆箱。"
+
+msgid "Add a car, a motorbike or a generator."
+msgstr "添加汽车、摩托车或发电机。"
+
+msgid "Add a thing, a box or a room to this location."
+msgstr "向此空间添加物品、收纳箱或房间。"
+
+msgid "Basics"
+msgstr "基本信息"
+
+msgid "Capture & Inbox"
+msgstr "采集与收件箱"
+
+msgid "Check what Kept read, fix anything wrong, then tap Accept."
+msgstr "请核对 Kept 识别出的内容,修正有误之处,然后轻点“接受”。"
+
+msgid "Choose how reminders reach you: in Kept, by email, push or a channel."
+msgstr "选择接收提醒的方式:在 Kept 内、通过邮件、推送通知或通知渠道。"
+
+msgid "Choose what reaches you, and how: in Kept, by email, push or a channel."
+msgstr "选择你希望接收哪些通知以及接收方式:Kept 应用内、邮件、推送或通知渠道。"
+
+msgid "Discard my change"
+msgstr "放弃我的修改"
+
+msgid "Download a location or all your data, with its photos and documents."
+msgstr "下载单个空间或你的全部数据,包含照片和文档。"
+
+msgid "Drop the file here, or choose it. Nothing is saved until you check it."
+msgstr "将文件拖到此处,或点击选择文件。在你核对确认前,不会保存任何内容。"
+
+msgid "Each home, garage or office you keep. Open one to see what's in it."
+msgstr "你管理的所有家、车库或办公室。打开任意空间查看其中的物品。"
+
+msgid "Each vehicle with its last reading and what's due next."
+msgstr "每辆车的最新读数及下次待办事项。"
+
+msgid "Every fill or charge, with what it cost and how far it went."
+msgstr "记录每次加油或充电,包括费用与行驶里程。"
+
+msgid "Every location you're in. Open one to change who's in it and what it tracks."
+msgstr "你加入的所有空间。打开任意空间可管理成员与追踪内容。"
+
+msgid "Every move, open or done. Tap one to see its boxes."
+msgstr "所有搬家记录(进行中或已完成)。轻点一项查看其中的箱子。"
+
+msgid "Every other section: your modules, Activity, Trash, Settings and Help."
+msgstr "其他所有板块:你的功能模块、动态、回收站、设置与帮助。"
+
+msgid "Every schedule, soonest first. Overdue ones lead."
+msgstr "按最近到期时间排序显示所有计划,已逾期的排在最前。"
+
+msgid "Everything in this location. Tap a thing to open it."
+msgstr "此空间中的所有物品。轻点物品即可打开。"
+
+msgid "Everything lent out or borrowed: who has it and when it's due back."
+msgstr "所有借出或借入的物品:当前保管人与应还日期。"
+
+msgid "Floors"
+msgstr "楼层"
+
+msgid "Import & export"
+msgstr "导入与导出"
+
+msgid "Invite someone by link or email, and pick their role."
+msgstr "通过链接或邮件邀请成员,并指定其角色。"
+
+msgid "Its sections"
+msgstr "内部分区"
+
+msgid "Keep leaves everything where it is. Discard removes only what the tour added: a thing goes to Trash for 30 days, a sample move is deleted. Your activity history stays either way."
+msgstr "选择“保留”会维持所有内容不变;选择“丢弃”仅会移除引导示例添加的内容(物品会移入回收站保留 30 天,示例搬家会被删除)。无论哪种方式,你的操作历史都会保留。"
+
+msgid "Log a reading, a service or fuel from here."
+msgstr "可在此记录读数、维护保养或加油记录。"
+
+msgid "Log it"
+msgstr "记录"
+
+msgid "Mark what's running low, lent out or due, on the map."
+msgstr "在平面图上标出快用完、已借出或即将到期的物品。"
+
+msgid "Name the move and say where it's going."
+msgstr "填写本次搬家名称并说明目的地。"
+
+msgid "Open a claim when it breaks under warranty, and follow the repair."
+msgstr "物品在保修期内损坏时,可在此发起保修理赔并跟进维修进度。"
+
+msgid "Pack"
+msgstr "打包"
+
+msgid "Packed, on the way and unpacked, counted."
+msgstr "已清点装箱中、运输中和已拆箱的箱子。"
+
+msgid "Paperwork & warranties"
+msgstr "单据与保修"
+
+msgid "Pick a floor, or All for the whole building."
+msgstr "选择一个楼层,或选择「全部」查看整栋建筑。"
+
+msgid "Pick what it is, then add the file to the thing it belongs to."
+msgstr "选择文件类别,然后将其添加到所属物品。"
+
+msgid "Pick where it comes from: a spreadsheet, Homebox or another Kept."
+msgstr "选择数据来源:电子表格、Homebox 或另一个 Kept 实例。"
+
+msgid "Receipts, manuals and warranty cards from every thing and room."
+msgstr "来自所有物品和房间的收据、说明书与保修卡。"
+
+msgid "Sample: Cordless drill"
+msgstr "示例:无绳电钻"
+
+msgid "Sample: Move"
+msgstr "示例:搬家"
+
+msgid "Save a search with its filters, and open it again in one tap."
+msgstr "保存当前搜索及筛选条件,下次可一键打开。"
+
+msgid "Schedules & reminders"
+msgstr "计划与提醒"
+
+msgid "Search & labels"
+msgstr "搜索与标签"
+
+msgid "Set something to repeat: every few months, or by the odometer."
+msgstr "设置重复周期:每隔几个月,或按里程表读数。"
+
+msgid "Settings & sharing"
+msgstr "设置与共享"
+
+msgid "Show me"
+msgstr "带我看看"
+
+msgid "Switch between what you captured and what everyone in your locations did."
+msgstr "在你自己采集的内容与空间内所有成员的操作之间切换。"
+
+msgid "Take a photo, or pick one with Gallery. It waits in your Inbox."
+msgstr "拍摄照片或从相册选取。照片会暂存在你的收件箱中等待处理。"
+
+msgid "Take the photo"
+msgstr "拍照"
+
+msgid "Tap Complete when it's done. The next date moves on."
+msgstr "完成后轻点「完成」,下次到期日期会自动顺延。"
+
+msgid "Tap Lend to hand it to someone and set when it's due back."
+msgstr "轻点「借出」即可将物品借给他人,并设置归还日期。"
+
+msgid "Tap Mark returned when it comes back."
+msgstr "归还后轻点「标为已归还」。"
+
+msgid "Tap Scan and point the camera at a Kept label. What it's on opens."
+msgstr "轻点「扫描」并将相机对准 Kept 标签,即可打开对应物品或位置。"
+
+msgid "The file"
+msgstr "文件"
+
+msgid "The place it's in. Tap to go back there."
+msgstr "它所在的位置。轻点可返回该处。"
+
+msgid "Things & places"
+msgstr "物品与位置"
+
+msgid "Turn modules on or off here: lending, vehicles, schedules and the rest."
+msgstr "在此开启或关闭各功能模块:借出、车辆、计划等。"
+
+msgid "Turn the map in 3D, or look straight down at the plan."
+msgstr "以 3D 视角旋转地图,或俯视平面图。"
+
+msgid "Type part of a name, a brand, a serial or a short ID. Filters narrow it down."
+msgstr "输入名称、品牌、序列号或短 ID 的一部分,配合筛选条件可进一步缩小范围。"
+
+msgid "Vehicles & fuel"
+msgstr "车辆与燃油"
+
+msgid "What runs out soon: warranties, insurance, a passport."
+msgstr "即将到期的事项:保修、保险、护照等。"
+
+msgid "What you're capturing"
+msgstr "当前采集内容"
+
+msgid "What's due"
+msgstr "即将到期"
+
+msgid "What's due, lent out or running low, counted. Tap a tile for its list."
+msgstr "统计即将到期、已借出及库存不足的物品。点击磁贴查看对应列表。"
+
+msgid "What's here"
+msgstr "这里有什么"
+
+msgid "Where the boxes are"
+msgstr "箱子所在位置"
+
+msgid "Your locations"
+msgstr "你的空间"
+
+msgid "Your moves"
+msgstr "你的搬家物品"
+
+msgid "Yours or everyone's"
+msgstr "你的或所有人的"
+
+msgid "Fill from photos"
+msgstr "从照片识别填充"
+
+msgid "Room photos"
+msgstr "房间照片"
+
+msgid "Keep room photos after review"
+msgstr "审核后保留房间照片"
+
+msgid "When you photograph a room, Kept cuts a picture for each thing it finds. Once you close the room in the inbox, the full photos are deleted, unless this is on: then they stay on the room's page."
+msgstr "拍摄房间照片时,Kept 会为识别出的每件物品裁切一张图片。当你在收件箱中关闭该房间后,完整原图会被删除;除非开启此选项,原图才会保留在房间页面中。"
+
+msgid "Photograph this room"
+msgstr "拍摄此房间"
+
+msgid "Placed by Kept from room photos: move them where they stand."
+msgstr "由 Kept 根据房间照片自动摆放:请将它们拖动到实际位置。"
+
+msgid "Photos of {name}"
+msgstr "{name} 的照片"
+
+msgid "{objects, plural, one {Photo {photo}: # thing} other {Photo {photo}: # things}}"
+msgstr "{objects, plural, one {照片 {photo}:# 件物品} other {照片 {photo}:# 件物品}}"
+
+msgid "Close this room?"
+msgstr "关闭此房间?"
+
+msgid "The photos stay on {0}. The drafts and their pictures stay in the inbox."
+msgstr "照片会保留在 {0} 上。草稿及其图片仍保留在收件箱中。"
+
+msgid "The full photos are deleted. The drafts and their own pictures stay in the inbox."
+msgstr "原图已删除。草稿及其裁剪图仍保留在收件箱中。"
+
+msgid "Room closed"
+msgstr "房间已闭合"
+
+msgid "Discard these photos?"
+msgstr "要丢弃这些照片吗?"
+
+msgid "The photos are deleted. Drafts already made stay in the inbox."
+msgstr "照片已删除。已创建的草稿仍保留在收件箱中。"
+
+msgid "Photos discarded"
+msgstr "照片已丢弃"
+
+msgid "Reading the photos again"
+msgstr "正在重新识别照片"
+
+msgid "{0, plural, one {Added # place} other {Added # places}}"
+msgstr "{0, plural, one {已添加 # 个位置} other {已添加 # 个位置}}"
+
+msgid "{0, plural, one {Marked # thing seen} other {Marked # things seen}}"
+msgstr "{0, plural, one {已将 # 件物品标记为已见到} other {已将 # 件物品标记为已见到}}"
+
+msgid "Photos of <0>{name}0>"
+msgstr "<0>{name}0> 的照片"
+
+msgid "Couldn't read"
+msgstr "无法读取"
+
+msgid "AI capture is off"
+msgstr "AI 识别录入已关闭"
+
+msgid "Waiting for the AI budget until {0}."
+msgstr "正在等待 AI 预算恢复,直至 {0}。"
+
+msgid "Listing what is in the photos…"
+msgstr "正在识别照片中的物品…"
+
+msgid "Reading photo {0} of {1}…"
+msgstr "正在识别第 {0} / {1} 张照片…"
+
+msgid "Kept couldn't read these photos. Retry, or take them again."
+msgstr "Kept 无法读取这些照片。请重试或重新拍摄。"
+
+msgid "AI capture is off here, so nothing was listed. The photos wait on <0>{name}0>."
+msgstr "此处已关闭 AI 采集,因此未识别清单。照片保留在 <0>{name}0> 上。"
+
+msgid "Nothing found in these photos."
+msgstr "在这些照片中未识别出物品。"
+
+msgid "This photo had more; take a closer one."
+msgstr "这张照片拍得不够清晰完整,请凑近重拍。"
+
+msgid "Couldn't read photo {0}"
+msgstr "无法读取照片 {0}"
+
+msgid "Photo {0}: not read"
+msgstr "照片 {0}:未读取"
+
+msgid "Photo {0} was removed"
+msgstr "照片 {0} 已被移除"
+
+msgid "Photo {0}: reading…"
+msgstr "照片 {0}:正在识别…"
+
+msgid "Furniture that holds things"
+msgstr "用于存放物品的家具"
+
+msgid "Add them as places in <0>{name}0>, so things can go in them."
+msgstr "将它们添加为 <0>{name}0> 内的位置,以便向其中存放物品。"
+
+msgid "Add as a place"
+msgstr "添加为位置"
+
+msgid "{0, plural, one {Add # place} other {Add all # places}}"
+msgstr "{0, plural, one {添加 # 个位置} other {添加全部 # 个位置}}"
+
+msgid "Seen"
+msgstr "已读"
+
+msgid "Its label is in the photos"
+msgstr "照片中包含它的标签"
+
+msgid "Same brand and model"
+msgstr "同品牌同型号"
+
+msgid "Same name"
+msgstr "同名"
+
+msgid "{0, plural, one {Mark # seen} other {Mark # seen}}"
+msgstr "{0, plural, one {将 # 项标为已读} other {将 # 项标为已读}}"
+
+msgid "{0, plural, one {# new thing to review below} other {# new things to review below}}"
+msgstr "{0, plural, one {下方有 # 件新物品待核对} other {下方有 # 件新物品待核对}}"
+
+msgid "{0, plural, one {# already in Kept} other {# already in Kept}}"
+msgstr "{0, plural, one {# 项已在 Kept 中} other {# 项已在 Kept 中}}"
+
+msgid "{0, plural, one {# piece of furniture to add as a place} other {# pieces of furniture to add as places}}"
+msgstr "{0, plural, one {# 件可添加为位置的家具} other {# 件可添加为位置的家具}}"
+
+msgid "Photographed {name} for Kept to list what is in it"
+msgstr "已拍摄 {name},交由 Kept 列出其中物品"
+
+msgid "Thing, receipt, label, reading or room. Pick one before the photo."
+msgstr "物品、收据、标签、读数或房间。拍照前请先选择模式。"
+
+msgid "A whole room"
+msgstr "整个房间"
+
+msgid "Up to five photos of a room. AI lists what's in them as drafts, skipping what Kept already has."
+msgstr "最多上传五张房间照片。AI 会将识别出的物品生成草稿,并自动跳过 Kept 中已有的物品。"
+
+msgid "Five photos at most. Send these, then take the next wall."
+msgstr "最多上传 5 张照片。请先提交这些,再拍摄下一面墙。"
+
+msgid "Room sent"
+msgstr "已发送房间"
+
+msgid "Kept lists what is in it in your Inbox."
+msgstr "Kept 会将其中的内容列在你的收件箱中。"
+
+msgid "{n, plural, one {About # photo} other {About # photos}}"
+msgstr "{n, plural, one {约 # 张照片} other {约 # 张照片}}"
+
+msgid "up to ~{0} tokens"
+msgstr "最多约 {0} 个 token"
+
+msgid "AI capture is off in <0>{0}0>. An owner or admin can turn it on."
+msgstr "<0>{0}0> 已关闭 AI 录入。空间所有者或管理员可以开启此功能。"
+
+msgid "Choose the room or the box these photos are of, above."
+msgstr "请在上方选择这些照片对应的房间或收纳箱。"
+
+msgid "No AI provider that reads photos is set up. Ask your instance admin."
+msgstr "未配置支持识别照片的 AI 服务商,请联系实例管理员。"
+
+msgid "Paused: the AI budget is used up until {0}."
+msgstr "已暂停:AI 预算已用尽,将于 {0} 恢复。"
+
+msgid "Paused: the AI budget is used up."
+msgstr "已暂停:AI 预算已用完。"
+
+msgid "Stand in the doorway; one photo per wall."
+msgstr "站在门口,每面墙拍一张照片。"
+
+msgid "Photos of this room"
+msgstr "此房间的照片"
+
+msgid "Remove photo {0}"
+msgstr "移除照片 {0}"
+
+msgid "In Try Kept no AI runs: every room photo gives the same sample results."
+msgstr "在体验模式 (Try Kept) 下不会运行真实 AI:每张房间照片都会返回相同的示例结果。"
+
+msgid "Use a sample room photo"
+msgstr "使用示例房间照片"
+
+msgid "Take up to {0} photos of the room."
+msgstr "最多拍摄 {0} 张房间照片。"
+
+msgid "{n, plural, one {# photo} other {# photos}}"
+msgstr "{n, plural, one {# 张照片} other {# 张照片}}"
+
+msgid "{n, plural, one {Send # photo} other {Send # photos}}"
+msgstr "{n, plural, one {发送 # 张照片} other {发送 # 张照片}}"
+
+msgid "Take photo: room"
+msgstr "拍照:房间"
+
+msgid "Room photo"
+msgstr "房间照片"
+
+msgid "Room photos merged"
+msgstr "已合并房间照片"
+
+msgid "Each room photo"
+msgstr "每张房间照片"
+
+msgid "Each room capture of several photos"
+msgstr "每次多张照片的房间采集"
+
+msgid "Count here"
+msgstr "清点此处"
+
+msgid "Scan every label in {name} in one walk"
+msgstr "一次巡检扫描 {name} 中的所有标签"
+
+msgid "Count this room"
+msgstr "盘点此房间"
+
+msgid "Count this box"
+msgstr "清点此箱子"
+
+msgid "Pack into this box"
+msgstr "装入此箱"
+
+msgid "Resume session"
+msgstr "继续盘点"
+
+msgid "Start a session"
+msgstr "开始会话"
+
+msgid "The camera isn't available"
+msgstr "摄像头不可用"
+
+msgid "Type codes, or use a USB or Bluetooth barcode scanner."
+msgstr "手动输入编码,或使用 USB / 蓝牙扫码枪。"
+
+msgid "Torch off"
+msgstr "关闭手电筒"
+
+msgid "Torch"
+msgstr "手电筒"
+
+msgid "The camera is off in this demo. Play a recorded walk past the sample labels."
+msgstr "此演示模式下相机已关闭。可播放一段经过示例标签的录制视频。"
+
+msgid "Stop the walk"
+msgstr "停止巡检"
+
+msgid "Play a sample walk"
+msgstr "播放示例漫游"
+
+msgid "This phone couldn't keep the session. Keep the screen open."
+msgstr "手机未能保持会话连接,请保持屏幕常亮。"
+
+msgid "Scan a box's label"
+msgstr "扫描箱子上的标签"
+
+msgid "Scan a place or a box"
+msgstr "扫描位置或箱子"
+
+msgid "This session is full: finish it, then start another."
+msgstr "本次会话已满:请先完成当前会话,再开始新的会话。"
+
+msgid "That's a place's label. Count it from its own page."
+msgstr "这是位置的标签。请前往该位置页面进行盘点。"
+
+msgid "A room can't be moved; scan things or boxes"
+msgstr "房间无法移动;请扫描物品或收纳箱"
+
+msgid "{found} of {all}"
+msgstr "{found} / {all}"
+
+msgid "Opening the session"
+msgstr "正在开启会话"
+
+msgid "Scan session"
+msgstr "扫码盘点会话"
+
+msgid "A count of <0>{0}0> is open on this phone."
+msgstr "此手机上正在进行 <0>{0}0> 的盘点。"
+
+msgid "A session is open on this phone."
+msgstr "此手机上存在已登录的会话。"
+
+msgid "{0, plural, one {# label read so far.} other {# labels read so far.}}"
+msgstr "{0, plural, one {目前已读取 # 个标签。} other {目前已读取 # 个标签。}}"
+
+msgid "Discard this session?"
+msgstr "要放弃此次盘点会话吗?"
+
+msgid "What it read is not saved."
+msgstr "识别读取的内容不会被保存。"
+
+msgid "Discard it and start another"
+msgstr "放弃并重新开始"
+
+msgid "Summary"
+msgstr "汇总"
+
+msgid "Count {0}"
+msgstr "盘点 {0}"
+
+msgid "Pack into boxes"
+msgstr "装入箱子"
+
+msgid "Move to {0}"
+msgstr "移至 {0}"
+
+msgid "You're a viewer: nothing is saved"
+msgstr "你当前为访客角色:所做更改不会保存"
+
+msgid "Scan the next box"
+msgstr "扫描下一个箱子"
+
+msgid "Scan where things go next"
+msgstr "接下来扫描物品去向"
+
+msgid "Going into {0}"
+msgstr "将导入至 {0}"
+
+msgid "Now moving to {0}"
+msgstr "当前移至 {0}"
+
+msgid "Nearly full: a session holds 5,000 labels."
+msgstr "即将达到上限:单次会话最多可容纳 5,000 个标签。"
+
+msgid "Last reads"
+msgstr "最近读数"
+
+msgid "in <0>{where}0>"
+msgstr "位于 <0>{where}0>"
+
+msgid "View only here"
+msgstr "此处仅可查看"
+
+msgid "Undo last read"
+msgstr "撤销上次读数"
+
+msgid "Pause"
+msgstr "暂停"
+
+msgid "All of {0}"
+msgstr "全部 {0}"
+
+msgid "Count"
+msgstr "盘点"
+
+msgid "Walk a place or a box: what you scan is seen; the summary shows what's missing."
+msgstr "巡检位置或箱子:扫描到的物品记为已找到,摘要会显示缺失项。"
+
+msgid "Check a place or a box: see what's there and what's missing. Viewers' counts aren't saved."
+msgstr "清点位置或箱子:查看有哪些在里面、有哪些缺失。查看者的清点记录不会被保存。"
+
+msgid "Pack into"
+msgstr "装入"
+
+msgid "Everything you scan goes into a box. Tap Target, then scan the next box."
+msgstr "你扫描的每件物品都会放入一个收纳箱。轻点「目标箱」,然后扫描下一个收纳箱。"
+
+msgid "Move to"
+msgstr "移至"
+
+msgid "Everything you scan moves to a place or a box."
+msgstr "扫描到的所有内容都会移入指定位置或收纳箱。"
+
+msgid "What to do"
+msgstr "处理方式"
+
+msgid "Counting <0>{0}0>"
+msgstr "正在盘点 <0>{0}0>"
+
+msgid "Packing into <0>{0}0>"
+msgstr "正在装入 <0>{0}0>"
+
+msgid "Moving to <0>{0}0>"
+msgstr "正在移至 <0>{0}0>"
+
+msgid "What to count"
+msgstr "要盘点的内容"
+
+msgid "Where things go"
+msgstr "存放去向"
+
+msgid "Scan the box's label"
+msgstr "扫描箱子上的标签"
+
+msgid "Include the places inside it"
+msgstr "包含其内部的位置"
+
+msgid "A box you scan counts what's inside it"
+msgstr "扫描收纳箱即可清点其中物品"
+
+msgid "Nothing changes until you finish: the summary shows what was found, what's missing and what's elsewhere, and you choose what to save."
+msgstr "在点击完成前不会保存任何更改:摘要会列出已找到、缺失以及在其他位置的物品,由你选择要保存的内容。"
+
+msgid "Waiting to save. It will save when you're online."
+msgstr "等待保存。联网后将自动保存。"
+
+msgid "Couldn't save your count of <0>{name}0>: you can no longer edit there."
+msgstr "无法保存你对 <0>{name}0> 的盘点结果:你已无权在此编辑。"
+
+msgid "Couldn't save this session: you can no longer edit there."
+msgstr "无法保存此会话:你已不再拥有该处的编辑权限。"
+
+msgid "Couldn't save this session. What it read is still on this phone."
+msgstr "无法保存此次盘点会话。已识别的内容仍保留在此手机上。"
+
+msgid "Undone."
+msgstr "已撤销。"
+
+msgid "Couldn't undo: something it changed has changed since."
+msgstr "无法撤销:该记录修改的对象此后又发生了变化。"
+
+msgid "Undo the whole session"
+msgstr "撤销整个盘点会话"
+
+msgid "Find in this summary"
+msgstr "在此汇总中查找"
+
+msgid "Found ({0})"
+msgstr "已找到({0})"
+
+msgid "Missing ({0})"
+msgstr "缺失({0})"
+
+msgid "Mark not here"
+msgstr "标为不在此处"
+
+msgid "Mark all not here"
+msgstr "全部标记为不在此处"
+
+msgid "No label ({0})"
+msgstr "无标签({0})"
+
+msgid "Found elsewhere ({0})"
+msgstr "在其他位置找到({0})"
+
+msgid "Move all here"
+msgstr "全部移至此处"
+
+msgid "In another location ({0})"
+msgstr "位于其他空间({0})"
+
+msgid "View only ({0})"
+msgstr "仅查看({0})"
+
+msgid "Unmatched ({0})"
+msgstr "未匹配({0})"
+
+msgid "Not in your Kept ({0})"
+msgstr "不在你的 Kept 中({0})"
+
+msgid "Check later ({0})"
+msgstr "稍后核对({0})"
+
+msgid "Couldn't save on this phone. Try again."
+msgstr "无法保存到此手机,请重试。"
+
+msgid "Back to scanning"
+msgstr "返回扫码"
+
+msgid "Show more"
+msgstr "显示更多"
+
+msgid "Saved."
+msgstr "已保存。"
+
+msgid "Seen: {seen}. Not here: {notHere}. Moved here: {moved}."
+msgstr "在场:{seen},不在场:{notHere},移至此处:{moved}。"
+
+msgid "Moved: {moved}."
+msgstr "已移动:{moved}。"
+
+msgid "Left out: {skipped} (trashed or no longer yours to change since)."
+msgstr "已跳过 {skipped}(已移入回收站或你已无权修改)。"
+
+msgid "Pack boxes"
+msgstr "装箱"
+
+msgid "Counted {name}: {found} of {expected}"
+msgstr "已盘点 {name}:在场 {found} / 应有 {expected}"
+
+msgid "Counted {name}: {found}"
+msgstr "已盘点 {name}:{found}"
+
+msgid "{count, plural, one {Packed # thing into {name}} other {Packed # things into {name}}}"
+msgstr "{count, plural, one {已将 # 件物品装入 {name}} other {已将 # 件物品装入 {name}}}"
+
+msgid "{count, plural, one {Packed # thing into boxes} other {Packed # things into boxes}}"
+msgstr "{count, plural, one {已将 # 件物品装箱} other {已将 # 件物品装箱}}"
+
+msgid "{count, plural, one {Moved # thing to {name}} other {Moved # things to {name}}}"
+msgstr "{count, plural, one {已将 # 件物品移至 {name}} other {已将 # 件物品移至 {name}}}"
+
+msgid "Scan many at once"
+msgstr "连续扫码"
+
+msgid "Tap Scan, then Start a session to count, pack or move many labels in one walk."
+msgstr "轻点“扫码”,然后选择“开始会话”,即可在一次走动中连续盘点、装箱或移动多个标签。"
+
+msgid "Count, pack or move"
+msgstr "清点、装箱或移动"
+
+msgid "Count checks what's there. Pack into and Move to put everything you scan in one box or place."
+msgstr "“盘点”用于核对现有物品;“装入”和“移至”可将你扫描的物品全部放入指定箱子或位置。"
+
+msgid "Pick a place, or scan its label. A box counts its contents; a room the places inside it."
+msgstr "选择一个位置,或扫描其标签。箱子盘点内部物品;房间盘点其中的位置。"
+
+msgid "Nothing changes until you finish"
+msgstr "在完成前不会应用任何更改"
+
+msgid "Finish shows what was found and what's missing. Missing things stay as they are unless you choose."
+msgstr "点击“完成”后将显示已盘点与缺失的物品。除非你主动选择处理方式,否则缺失物品将保持原状。"
+
+msgid "Scanning"
+msgstr "正在扫描"
+
+msgid "No AI runs in this demo"
+msgstr "此演示中不会运行 AI"
+
+msgid "Mini PC"
+msgstr "迷你主机"
+
+msgid "NAS"
+msgstr "NAS"
+
+msgid "Raspberry Pi or SBC"
+msgstr "树莓派或单板机 (SBC)"
+
+msgid "Network switch"
+msgstr "网络交换机"
+
+msgid "Patch panel"
+msgstr "配线架"
+
+msgid "UPS"
+msgstr "UPS"
+
+msgid "Server rack 24U"
+msgstr "24U 服务器机柜"
+
+msgid "Server rack 42U"
+msgstr "42U 服务器机柜"
+
+msgid "Wall rack 6U"
+msgstr "壁挂机柜 6U"
+
+msgid "Wall rack 12U"
+msgstr "壁挂机柜 12U"
+
+msgid "Missing a shape? <0>Request it0>, or browse the <1>shape library1>."
+msgstr "找不到想要的形状?<0>申请添加0>,或浏览<1>形状库1>。"
+
+msgid "{count, plural, one {# chapter} other {# chapters}}"
+msgstr "{count, plural, one {# 个章节} other {# 个章节}}"
+
+msgid "Chapter {c} of {n}"
+msgstr "第 {c} / {n} 节"
+
+msgid "step {done} of {total}"
+msgstr "第 {done} 步,共 {total} 步"
+
+msgid "Continue the tour"
+msgstr "继续导览"
+
+msgid "Next: {chapter}"
+msgstr "下一节:{chapter}"
+
+msgid "One after another, on the real screens. Stop any time."
+msgstr "在真实界面上逐步演示,随时可以停止。"
+
+msgid "Stop here"
+msgstr "到此为止"
+
+msgid "Take the tour"
+msgstr "开始导览"
+
+msgid "The tour"
+msgstr "功能导览"
+
+msgid "A Homebox location, not an item, so it's skipped: places come from the items' location column."
+msgstr "这是 Homebox 位置而非物品,因此已跳过:位置将根据物品的 location 列自动生成。"
+
+msgid "It has no manifest.json, so it isn't an export from Homebox v0.26.1 or newer. A Homebox older than v0.26 can't make one: update a copy of it to v0.27.0 and export again, or import its spreadsheet (CSV) export instead."
+msgstr "压缩包中缺少 manifest.json,因此它不是 Homebox v0.26.1 及以上版本的导出文件。低于 v0.26 的 Homebox 无法生成此文件:请先将其副本升级至 v0.27.0 后重新导出,或改用电子表格 (CSV) 导出导入。"
+
+msgid "A Homebox older than v0.26 makes a spreadsheet instead of an export ZIP. Import it as a spreadsheet: names, places, tags, purchases, warranties, sales and old labels come across. For photos, files and maintenance too, update a copy of Homebox to v0.26.1 or newer (v0.27.0 recommended) and export the ZIP."
+msgstr "低于 v0.26 版本的 Homebox 会导出电子表格而非 ZIP 压缩包。请按电子表格导入:名称、位置、分类标签、购买记录、保修、售出记录和旧标签都会导入。如需一并导入照片、文件和维护记录,请先将 Homebox 副本升级至 v0.26.1 或更高版本(推荐 v0.27.0)后再导出 ZIP。"
+
+msgid "Archived items aren't imported, sold ones included."
+msgstr "已归档物品(包括已售出物品)不会导入。"
+
+msgid "Coming from an older Homebox"
+msgstr "来自旧版 Homebox"
+
+msgid "Import a Homebox export instead"
+msgstr "改为导入 Homebox 导出文件"
+
+msgid "Import it as a spreadsheet"
+msgstr "作为电子表格导入"
+
+msgid "Kept reads its asset IDs, so old Homebox labels still scan, and its archived and sold items, warranties and insured column. A spreadsheet can't carry photos, files, maintenance or items inside items: for those, update a copy of Homebox to v0.26.1 or newer (v0.27.0 recommended) and import its export ZIP."
+msgstr "Kept 会读取其资产 ID(旧版 Homebox 标签仍可扫码识别),以及已归档/已售出物品、保修和已投保列。电子表格无法携带照片、附件、维护记录或嵌套物品;如需完整迁移,请先将 Homebox 升级至 v0.26.1 或更高版本(推荐 v0.27.0)再导入其导出的 ZIP 包。"
+
+msgid "One with a sale still ends sold."
+msgstr "带有售出记录的物品仍会标记为已售出。"
+
+msgid "Read by the Homebox preset"
+msgstr "由 Homebox 预设读取"
+
+msgid "Restart Homebox and export again: v0.26 exports once each time it starts. v0.27.0 doesn't have this limit."
+msgstr "请重启 Homebox 后再次导出:v0.26 每次启动仅支持导出一次。v0.27.0 没有此限制。"
+
+msgid "This is Homebox's spreadsheet export"
+msgstr "这是 Homebox 的电子表格导出文件"
+
+msgid "Archived"
+msgstr "已归档"
+
+msgid "Unarchive"
+msgstr "取消归档"
+
+msgid "Still yours, put away, as in Homebox's archive. One with a sale ends sold instead."
+msgstr "仍归你所有但已收起存放,对应 Homebox 的归档状态。带有出售记录的物品会转为已售出。"
+
+msgid "Label {at}, row {rn}, column {cn2}: {nm}, {cd}"
+msgstr "标签 {at},第 {rn} 行第 {cn2} 列:{nm},{cd}"
+
+msgid "Label {at}, row {rn}, column {cn2}: {cd}"
+msgstr "标签 {at},第 {rn} 行第 {cn2} 列:{cd}"
+
+msgid "Each label: QR code, name, where it is and short ID"
+msgstr "每张标签包含二维码、名称、所在位置和短 ID"
+
+msgid "Each label: QR code and short ID"
+msgstr "每张标签:二维码与短 ID"
+
+msgid "Type a model id instead."
+msgstr "改为手动输入模型 ID。"
+
+msgid "free: shared, may be busy"
+msgstr "免费:共享资源,可能较忙"
+
+msgid "not set"
+msgstr "未设置"
+
+msgid "Put all in…"
+msgstr "全部放入…"
+
+msgid "Counts"
+msgstr "盘点"
+
+msgid "Past counts"
+msgstr "历史清点"
+
+msgid "Every count of {name}, with what was missing"
+msgstr "{name} 的历次盘点及缺失清单"
+
+msgid "{pct}% of things here have labels."
+msgstr "此处 {pct}% 的物品已有标签。"
+
+msgid "Print labels for the rest"
+msgstr "打印其余标签"
+
+msgid "Count in progress by <0>{0}0>"
+msgstr "由 <0>{0}0> 进行中的盘点"
+
+msgid "Join"
+msgstr "加入"
+
+msgid "See this count"
+msgstr "查看此次清点"
+
+msgid "Found short ({0})"
+msgstr "数量不足({0})"
+
+msgid "{found} of {of}"
+msgstr "{found} / {of}"
+
+msgid "Mark the rest not here"
+msgstr "将剩余物品标为不在此处"
+
+msgid "Found by others ({0})"
+msgstr "其他人找到的({0})"
+
+msgid "found by <0>{0}0>"
+msgstr "由 <0>{0}0> 找到"
+
+msgid "With {0} ({1})"
+msgstr "在 {0} 处({1})"
+
+msgid "Lent out ({0})"
+msgstr "已借出({0})"
+
+msgid "In repair ({0})"
+msgstr "维修中({0})"
+
+msgid "Not counted: {area} ({0})"
+msgstr "未计入:{area}({0})"
+
+msgid "I checked it"
+msgstr "我已核对"
+
+msgid "Others are counting here too: finishing needs a connection."
+msgstr "其他人也正在此处盘点:完成盘点需要联网。"
+
+msgid "Every count is kept"
+msgstr "每次盘点记录都会保留"
+
+msgid "Counts lists each count and box check: what was found, what was missing, and what changed since the last one."
+msgstr "「盘点记录」会列出每次盘点与箱内核对的详情:找到了什么、少了什么,以及自上次以来的变化。"
+
+msgid "{a} of {b} found"
+msgstr "已找到 {a} / {b}"
+
+msgid "Box check of {name}"
+msgstr "箱内清点:{name}"
+
+msgid "by <0>{0}0>"
+msgstr "由 <0>{0}0>"
+
+msgid "What it should hold ({0})"
+msgstr "应包含物品({0})"
+
+msgid "Found in it from elsewhere ({0})"
+msgstr "在其中发现了来自别处的物品({0})"
+
+msgid "Missing"
+msgstr "缺失"
+
+msgid "Found elsewhere"
+msgstr "在其他位置找到"
+
+msgid "Moved here"
+msgstr "已移至此位置"
+
+msgid "Marked not here"
+msgstr "已标记为不在此处"
+
+msgid "In the Trash"
+msgstr "在回收站中"
+
+msgid "Not counted: {0}"
+msgstr "未计入:{0}"
+
+msgid "Count of {name}"
+msgstr "{name} 的盘点"
+
+msgid "Still open"
+msgstr "仍在进行中"
+
+msgid "{minutes, plural, one {# minute} other {# minutes}}"
+msgstr "{minutes, plural, one {# 分钟} other {# 分钟}}"
+
+msgid "finished by <0>{0}0>"
+msgstr "由 <0>{0}0> 完成"
+
+msgid "Counted by <0>{readers}0>"
+msgstr "盘点人:<0>{readers}0>"
+
+msgid "Done for the planned count <0>{0}0>"
+msgstr "已完成盘点计划 <0>{0}0>"
+
+msgid "Since the previous count"
+msgstr "自上次盘点以来"
+
+msgid "{0, plural, one {# newly missing} other {# newly missing}}"
+msgstr "{0, plural, one {新增 # 项缺失} other {新增 # 项缺失}}"
+
+msgid "{0, plural, one {# found again} other {# found again}}"
+msgstr "{0, plural, one {已重新找回 #} other {已重新找回 #}}"
+
+msgid "{0, plural, one {# new thing} other {# new things}}"
+msgstr "{0, plural, one {# 件新物品} other {# 件新物品}}"
+
+msgid "Open the previous count ({0})"
+msgstr "打开上次盘点({0})"
+
+msgid "Counts saved before Kept 1.14 didn't record what was missing or elsewhere."
+msgstr "Kept 1.14 之前保存的盘点记录未记录哪些物品缺失或在其他位置。"
+
+msgid "now in <0>{now}0>"
+msgstr "现位于 <0>{now}0>"
+
+msgid "was in <0>{was}0>"
+msgstr "曾位于 <0>{was}0>"
+
+msgid "read by <0>{0}0>"
+msgstr "由 <0>{0}0> 识别"
+
+msgid "{months, plural, one {Counted every month} other {Counted every # months}}"
+msgstr "{months, plural, one {每月盘点一次} other {每 # 个月盘点一次}}"
+
+msgid "Count regularly"
+msgstr "定期清点"
+
+msgid "The next count is overdue"
+msgstr "下次盘点已逾期"
+
+msgid "Next count due {next}"
+msgstr "下次清点到期日:{next}"
+
+msgid "A reminder to count {name} every few months"
+msgstr "每隔几个月盘点一次 {name} 的提醒"
+
+msgid "Planned count"
+msgstr "计划盘点"
+
+msgid "A whole number of months, {min} to {max}."
+msgstr "请输入 {min} 到 {max} 之间的整数月数。"
+
+msgid "Count {name}"
+msgstr "盘点 {name}"
+
+msgid "Planned: count {name} regularly"
+msgstr "已计划:定期盘点 {name}"
+
+msgid "Stopped the planned count"
+msgstr "已停止计划盘点"
+
+msgid "Counting <0>{name}0> (and the places inside it) marks it done; you get a reminder a week before it's due."
+msgstr "盘点 <0>{name}0>(及其内部所有位置)后即标记为完成;到期前一周你会收到提醒。"
+
+msgid "Every how many months"
+msgstr "每隔几个月"
+
+msgid "Stop counting regularly"
+msgstr "停止定期盘点"
+
+msgid "Box checks"
+msgstr "箱内检查"
+
+msgid "Had missing"
+msgstr "存在缺失"
+
+msgid "Counted"
+msgstr "已清点"
+
+msgid "Search counts"
+msgstr "搜索盘点记录"
+
+msgid "Search by what was counted"
+msgstr "按盘点内容搜索"
+
+msgid "by place"
+msgstr "按位置"
+
+msgid "No counts yet"
+msgstr "暂无盘点记录"
+
+msgid "Count a place or a box from Scan: every count and box check is kept here, with what was found and what was missing."
+msgstr "通过扫码清点位置或箱子:每次盘点与开箱清点记录都会保存在这里,包含已找到与缺失的物品。"
+
+msgid "{missing, plural, one {# missing} other {# missing}}"
+msgstr "{missing, plural, one {缺失 # 项} other {缺失 # 项}}"
+
+msgid "Move it anyway"
+msgstr "仍然移动"
+
+msgid "Parts"
+msgstr "配件"
+
+msgid "Move to Trash anyway"
+msgstr "仍要移入回收站"
+
+msgid "How many came back: 1 to {0}."
+msgstr "归还数量:1 到 {0}。"
+
+msgid "{back} of {all} came back"
+msgstr "已归还 {back} / {all}"
+
+msgid "in <0>{0}0>"
+msgstr "位于 <0>{0}0>"
+
+msgid "Came back"
+msgstr "已归还"
+
+msgid "Not returned"
+msgstr "未归还"
+
+msgid "How many came back"
+msgstr "归还数量"
+
+msgid "Of {0}. The rest stays out."
+msgstr "来自 {0}。其余部分不包含在内。"
+
+msgid "Condition it came back in"
+msgstr "归还时成色"
+
+msgid "Update its condition"
+msgstr "更新物品状况"
+
+msgid "It stays with them; reminders go on."
+msgstr "物品仍留在对方处,相关提醒将继续生效。"
+
+msgid "It is marked lost, never deleted: its history stays."
+msgstr "仅标记为遗失,绝不删除:其历史记录将保留。"
+
+msgid "{lines, plural, one {Lent to {0}} other {Lent to {1}: # things}}"
+msgstr "{lines, plural, one {借给 {0}} other {借给 {1}:# 件物品}}"
+
+msgid "Stayed here: {0}"
+msgstr "留在此处:{0}"
+
+msgid "Optional. Kept reminds you, never them, two days before and when it's overdue."
+msgstr "可选。Kept 会在到期前两天和逾期时提醒你,绝不会联系对方。"
+
+msgid "What goes with it"
+msgstr "随附物品"
+
+msgid "Everything inside goes too"
+msgstr "里面的所有物品也会一并处理"
+
+msgid "and what is inside it"
+msgstr "以及其中的所有物品"
+
+msgid "Each keeps its own record. Something already lent or in repair stays here."
+msgstr "每件物品均保留各自记录。已借出或维修中的物品将留在原处。"
+
+msgid "Parts kept elsewhere"
+msgstr "存放在别处的配件"
+
+msgid "Parts not in the kit"
+msgstr "不在套件中的部件"
+
+msgid "Lend <0>{0}0> too (in <1>{1}1>)"
+msgstr "同时借出 <0>{0}0>(位于 <1>{1}1>)"
+
+msgid "Lend <0>{0}0> too"
+msgstr "同时借出 <0>{0}0>"
+
+msgid "Condition going out"
+msgstr "借出时状况"
+
+msgid "This is with {0}"
+msgstr "当前在 {0} 处"
+
+msgid "{0} is lent out. Mark it returned first, or go ahead anyway?"
+msgstr "{0} 目前处于借出状态。要先行标记为已归还,还是继续操作?"
+
+msgid "Mark it returned first, or go ahead anyway?"
+msgstr "要将其先标为已归还,还是直接继续?"
+
+msgid "with <0>{0}0>"
+msgstr "包含 <0>{0}0>"
+
+msgid "Marked lost"
+msgstr "已标记为丢失"
+
+msgid "Mark lost"
+msgstr "标记为丢失"
+
+msgid "Lent with what is inside"
+msgstr "连同内部物品一并借出"
+
+msgid "{0, plural, one {# lost} other {# lost}}"
+msgstr "{0, plural, one {# 项遗失} other {# 项遗失}}"
+
+msgid "came back {0}"
+msgstr "已于 {0} 归还"
+
+msgid "Went with"
+msgstr "随同移动"
+
+msgid "Mark everything returned"
+msgstr "全部标记为已归还"
+
+msgid "Loading the kit"
+msgstr "正在加载套件"
+
+msgid "Not a kit"
+msgstr "非套件"
+
+msgid "Make this a kit"
+msgstr "设为套件"
+
+msgid "A kit remembers what should be in it: move a part out or lend it, and the kit still knows."
+msgstr "套件会记住其中应包含哪些物品:即使将某个部件移出或借出,套件依然会记录它的归属。"
+
+msgid "In the kit"
+msgstr "套件内含内容"
+
+msgid "Elsewhere"
+msgstr "在其他位置"
+
+msgid "With someone"
+msgstr "在他人处"
+
+msgid "Put it back anyway"
+msgstr "仍然放回"
+
+msgid "Put back in {0}"
+msgstr "已放回 {0}"
+
+msgid "Couldn't put it back"
+msgstr "无法放回原处"
+
+msgid "No longer a kit?"
+msgstr "不再作为套件?"
+
+msgid "Its parts stay where they are; only the list goes. You can undo this for 7 days."
+msgstr "套件中的部件会留在原处,仅删除套件列表本身。7 天内可撤销。"
+
+msgid "No longer a kit"
+msgstr "已取消套件标记"
+
+msgid "With <0>{0}0> since {1}"
+msgstr "自 {1} 起由 <0>{0}0> 保管"
+
+msgid "{0, plural, one {# part not in the kit} other {# parts not in the kit}}"
+msgstr "{0, plural, one {# 个配件不在套件内} other {# 个配件不在套件内}}"
+
+msgid "Put back"
+msgstr "放回"
+
+msgid "Check this kit"
+msgstr "清点此套件"
+
+msgid "Edit parts"
+msgstr "编辑配件"
+
+msgid "Parts of {0}"
+msgstr "{0} 的部件"
+
+msgid "Make {0} a kit"
+msgstr "将 {0} 设为套件"
+
+msgid "Parts changed"
+msgstr "配件已更改"
+
+msgid "Made a kit"
+msgstr "已创建套件"
+
+msgid "Nothing in it yet: add its parts below."
+msgstr "里面还是空的:请在下方添加它的组成部分。"
+
+msgid "Add a part"
+msgstr "添加部件"
+
+msgid "Borrowed from {person}"
+msgstr "借自 {person}"
+
+msgid "Lent to {person}"
+msgstr "借给 {person}"
+
+msgid "Came back from {person}, {condition}"
+msgstr "由 {person} 归还,成色:{condition}"
+
+msgid "Came back from {person}"
+msgstr "已由 {person} 归还"
+
+msgid "Lost by {person}"
+msgstr "被 {person} 遗失"
+
+msgid "{count, plural, one {Lent {name} to {person}} other {Lent {name} to {person}, # things}}"
+msgstr "{count, plural, one {已将 {name} 借给 {person}} other {已将 {name} 等 # 件物品借给 {person}}}"
+
+msgid "Lent {name} to {person}"
+msgstr "已将 {name} 借给 {person}"
+
+msgid "Changed the hand-over"
+msgstr "更改了交接记录"
+
+msgid "Made {name} a kit"
+msgstr "已将 {name} 设为套件"
+
+msgid "Changed the parts of {name}"
+msgstr "修改了 {name} 的配件"
+
+msgid "{name} is no longer a kit"
+msgstr "{name} 已不再是套件"
+
+msgid "Kits"
+msgstr "套装"
+
+msgid "A kit remembers what should be in it. Its parts say where each one is: in the kit, elsewhere, or with someone."
+msgstr "套件会记录其中应包含的物品,其配件状态会显示每一项是在套件内、在其他位置,还是借给了某人。"
+
+msgid "Incomplete kits"
+msgstr "未齐套件"
+
+msgid "With {who} (in {box}) since {since} · due {due}"
+msgstr "由 {who} 借走(装在 {box} 中),自 {since} 起 · {due} 到期"
+
+msgid "With {who} (in {box}) since {since}"
+msgstr "由 {who} 借走(装在 {box} 中),自 {since} 起"
+
+msgid "{label}: all of {summary}"
+msgstr "{label}:{summary} 的全部内容"
+
+msgid "Add tag"
+msgstr "添加分类标签"
+
+msgid "Add tags…"
+msgstr "添加分类标签…"
+
+msgid "Amber"
+msgstr "琥珀色"
+
+msgid "Blue"
+msgstr "蓝色"
+
+msgid "Brown"
+msgstr "棕色"
+
+msgid "by tag"
+msgstr "按分类标签"
+
+msgid "Couldn't change the tags"
+msgstr "无法修改分类标签"
+
+msgid "Create “<0>{typed}0>”"
+msgstr "创建“<0>{typed}0>”"
+
+msgid "Cyan"
+msgstr "青色"
+
+msgid "Green"
+msgstr "绿色"
+
+msgid "Grey"
+msgstr "灰色"
+
+msgid "has all of"
+msgstr "包含全部"
+
+msgid "Indigo"
+msgstr "靛蓝色"
+
+msgid "Its tags aren't kept: in Kept only things have tags."
+msgstr "其分类标签不会保留:在 Kept 中仅物品可添加分类标签。"
+
+msgid "No colour"
+msgstr "无颜色"
+
+msgid "No tag"
+msgstr "无分类标签"
+
+msgid "No tags yet."
+msgstr "暂无分类标签。"
+
+msgid "Orange"
+msgstr "橙色"
+
+msgid "Pink"
+msgstr "粉色"
+
+msgid "Red"
+msgstr "红色"
+
+msgid "Remove tags…"
+msgstr "移除分类标签…"
+
+msgid "Tagged {shown}"
+msgstr "已添加分类标签:{shown}"
+
+msgid "Tags changed"
+msgstr "分类标签已更改"
+
+msgid "Tags: <0>{names}0>"
+msgstr "分类标签:<0>{names}0>"
+
+msgid "Take {0} off"
+msgstr "移除 {0}"
+
+msgid "Teal"
+msgstr "青色"
+
+msgid "Things tagged {0}"
+msgstr "带有分类标签「{0}」的物品"
+
+msgid "Took off {shown}"
+msgstr "已取消展示 {shown}"
+
+msgid "Violet"
+msgstr "紫罗兰色"
+
+msgid "Offline, search uses the words, the location, the type and the tags. The other filters apply when you're back online."
+msgstr "离线状态下,搜索仅使用关键词、空间、类型和分类标签。其余筛选条件将在恢复联网后生效。"
+
+msgid "A serial number"
+msgstr "序列号"
+
+msgid "A serial number or a barcode"
+msgstr "序列号或条形码"
+
+msgid "Keep the code as"
+msgstr "将编号保留为"
+
+msgid "Kept stores it as the serial number."
+msgstr "Kept 会将其保存为序列号。"
+
+msgid "Kept stores it as the serial number or the barcode: you pick."
+msgstr "Kept 可将其保存为序列号或条码:由你选择。"
+
+msgid "Kept stores the barcode and serial number with it."
+msgstr "Kept 会将其与条形码和序列号一并保存。"
+
+msgid "Add one in Sign-in and security"
+msgstr "请在“登录与安全”中添加"
+
+msgid "That passkey isn't one this account signs in with. A device's app lock can't sign you in. Sign in another way, then add a passkey in Settings → Sign-in and security."
+msgstr "该通行密钥不是当前账号的登录密钥。设备的应用锁无法用于登录账号。请先用其他方式登录,再前往「设置 → 登录与安全」添加通行密钥。"
+
+msgid "They add one in Sign-in and security"
+msgstr "请在“登录与安全”中添加"
+
+msgid "Kept emails you a sign-in link; opening it confirms the address. Opening it also removes this account's password, passkeys and other sessions, so nobody who set them up before you keeps a way in. Then come back here within ten minutes."
+msgstr "Kept 会向你发送一封包含登录链接的邮件,打开该链接即可验证邮箱。打开链接同时会清除此账户的密码、通行密钥及其他登录会话,确保此前设置过登录方式的人无法继续访问。随后请在 10 分钟内返回此处。"
+
+msgid "After this, signing in with a sign-in link or Google also asks for a 6-digit code from an authenticator app (1Password, Google Authenticator, Aegis…)."
+msgstr "启用后,通过登录链接或 Google 登录时,还需输入验证器应用(如 1Password、Google Authenticator、Aegis 等)生成的 6 位验证码。"
+
+msgid "That's your only way to sign in. Add another passkey or link another sign-in first."
+msgstr "这是你唯一的登录方式。请先添加另一个通行密钥或关联其他登录方式。"
+
+msgid "A location you belong to asks for two-factor. Add a passkey first, then turn the authenticator app off."
+msgstr "你所在的某个空间要求启用双重验证。请先添加通行密钥,再关闭验证器应用。"
+
+msgid "Loading your sign-in settings"
+msgstr "正在加载你的登录设置"
+
+msgid "Passkeys"
+msgstr "通行密钥"
+
+msgid "Add a passkey"
+msgstr "添加通行密钥 (Passkey)"
+
+msgid "Sign in with Face ID, a fingerprint or your phone's screen lock instead of typing a password. A passkey counts as two-factor on its own."
+msgstr "使用面容 ID、指纹或手机锁屏替代密码登录。通行密钥本身即视作双重验证。"
+
+msgid "This browser can't add a passkey. Try another browser or device."
+msgstr "此浏览器无法添加通行密钥。请尝试其他浏览器或设备。"
+
+msgid "No passkeys yet"
+msgstr "暂无通行密钥"
+
+msgid "Passkey"
+msgstr "通行密钥"
+
+msgid "This device only"
+msgstr "仅此设备"
+
+msgid "Passkey added"
+msgstr "通行密钥已添加"
+
+msgid "Use {NAME_MAX} characters or fewer."
+msgstr "请控制在 {NAME_MAX} 个字符以内。"
+
+msgid "Your browser asks for Face ID, a fingerprint or your screen lock. The passkey is kept by this device or your password manager; Kept never sees it."
+msgstr "浏览器会请求面容 ID、指纹或屏幕锁验证。通行密钥仅保存在此设备或你的密码管理器中,Kept 永远无法读取它。"
+
+msgid "So you can tell your passkeys apart."
+msgstr "方便你区分不同的通行密钥。"
+
+msgid "Adding a passkey needs a sign-in in the last ten minutes."
+msgstr "添加通行密钥需要过去 10 分钟内有过登录验证。"
+
+msgid "Sign in once with a link sent to your email address, then add the passkey."
+msgstr "请先通过发送到你邮箱的链接登录一次,然后再添加通行密钥。"
+
+msgid "This device already has a passkey for your account."
+msgstr "此设备已为你的账户创建过通行密钥。"
+
+msgid "Rename passkey"
+msgstr "重命名通行密钥"
+
+msgid "Passkey renamed"
+msgstr "通行密钥已重命名"
+
+msgid "Remove <0>{name}0>?"
+msgstr "移除 <0>{name}0>?"
+
+msgid "Passkey removed"
+msgstr "通行密钥已移除"
+
+msgid "It stops signing you in, and every other device is signed out. The passkey itself stays on the device until you delete it there."
+msgstr "该密钥将无法再用于登录,其他所有设备也会退出登录。通行密钥本身仍会保留在原设备上,直至你在该设备中删除。"
+
+msgid "Authenticator app"
+msgstr "验证器应用"
+
+msgid "Two-factor with an authenticator app"
+msgstr "使用身份验证器应用进行双重验证"
+
+msgid "Off. Some locations ask for it; until you turn it on, or sign in with a passkey, they stay hidden for you."
+msgstr "已关闭。部分空间要求启用双重验证;在开启或改用通行密钥登录前,这些空间对你不可见。"
+
+msgid "{0} of {1} backup codes left"
+msgstr "剩余 {0} / {1} 个备用恢复码"
+
+msgid "New backup codes"
+msgstr "新的备用恢复码"
+
+msgid "Set up again"
+msgstr "重新配置"
+
+msgid "Make new codes"
+msgstr "生成新编码"
+
+msgid "Ten new codes, shown once. Your old backup codes stop working, and every other device is signed out."
+msgstr "系统已生成十个仅显示一次的新恢复码。旧备用恢复码已失效,其他所有设备已退出登录。"
+
+msgid "The new app is set up. Codes from the old one no longer work."
+msgstr "新验证器应用已配置完成,旧应用中的验证码将不再有效。"
+
+msgid "Until you enter a code from the new app, your current app keeps working. Close this and nothing changes."
+msgstr "在输入新验证器应用的验证码之前,你当前的验证器仍可正常使用。关闭此窗口不会做出任何更改。"
+
+msgid "Use the new app"
+msgstr "使用新版应用"
+
+msgid "For a new phone or another authenticator app. Your current app keeps working until the new one is set up; then it stops, your backup codes are replaced, and every other device is signed out."
+msgstr "用于更换新手机或其他验证器应用。在新的验证器设置完成前,当前应用仍可继续使用;设置完成后,旧应用将停用,备用恢复码将被替换,且其他所有设备都会退出登录。"
+
+msgid "Turn off two-factor?"
+msgstr "关闭双重验证?"
+
+msgid "Two-factor is off"
+msgstr "双重验证已关闭"
+
+msgid "Signing in stops asking for a code, your backup codes stop working, and every other device is signed out. Locations that ask for two-factor stay hidden until you sign in with a passkey or turn it on again."
+msgstr "关闭后,登录时不再要求验证码,备用恢复码将失效,其他所有设备也会退出登录。要求双重验证的空间将保持隐藏,直到你使用通行密钥登录或重新开启双重验证。"
+
+msgid "Sign-in and security"
+msgstr "登录与安全"
+
+msgid "Backup codes"
+msgstr "备用恢复码"
+
+msgid "Renamed a passkey"
+msgstr "重命名了通行密钥"
+
+msgid "Removed a passkey"
+msgstr "已移除一个通行密钥"
+
+msgid "Started setting up two-factor"
+msgstr "开始配置双重验证"
+
+msgid "Turned off two-factor"
+msgstr "已关闭双重验证"
+
+msgid "Made new backup codes"
+msgstr "已生成新的备用恢复码"
+
+msgid "Set up two-factor again"
+msgstr "重新设置双重验证"
+
+msgid "Unlock with Face ID or fingerprint"
+msgstr "使用面容 ID 或指纹解锁"
+
+msgid "Unlocks Kept on this device only. To sign in with a passkey, add one in <0>Sign-in and security0>."
+msgstr "仅用于解锁此设备上的 Kept。如需使用通行密钥登录,请在<0>登录与安全0>中添加。"
+
+msgid "Added a passkey"
+msgstr "已添加通行密钥"
+
+msgid "Turned on two-factor"
+msgstr "已开启双重验证"
+
+msgid "Unlinked an outside sign-in"
+msgstr "已解绑一个外部登录方式"
+
+msgid "A location you belong to asks for two-factor. Turn on the authenticator app before removing your last passkey."
+msgstr "你所在的某个空间要求开启双重验证。请先启用验证器应用,再移除你的最后一个通行密钥。"
+
+msgid "The page is already {stockTitle} with no margins: keep the print dialog's defaults and scale 100%, so each label lands in its cell."
+msgstr "页面已按无边距 {stockTitle} 排版:请保持打印对话框默认设置并将缩放设为 100%,以确保每个标签准确落入格内。"
+
+msgid "Set aside"
+msgstr "暂存待用"
+
+msgid "Did this sheet print?"
+msgstr "这张标签纸打印好了吗?"
+
+msgid "Printed OK"
+msgstr "打印正常"
+
+msgid "Not printed"
+msgstr "未打印"
+
+msgid "These labels are already on a sheet that isn’t confirmed printed"
+msgstr "这些标签已在尚未确认打印的标签纸上"
+
+msgid "Open that sheet"
+msgstr "打开该表"
+
+msgid "Made {when} on {stock}. Open it to print it or confirm it printed, or print a new sheet below."
+msgstr "创建于 {when},使用 {stock} 纸张。打开即可打印或确认已打印,或在下方打印新标签页。"
+
+msgid "{0, plural, one {# name is too long for this label} other {# names are too long for this label}}"
+msgstr "{0, plural, one {# 个名称过长,无法印在此标签上} other {# 个名称过长,无法印在此标签上}}"
+
+msgid "Shorten them, or pick a bigger label. Printed as they are, they won't fit."
+msgstr "请缩短文字,或换用更大尺寸的标签。按当前内容直接打印会超出标签范围。"
+
+msgid "Rename {0}"
+msgstr "重命名 {0}"
+
+msgid "{more, plural, one {# more} other {# more}}"
+msgstr "{more, plural, one {另外 # 项} other {另外 # 项}}"
+
+msgid "{count}: {list}"
+msgstr "{count}:{list}"
+
+msgid "Made {made}"
+msgstr "已创建 {made}"
+
+msgid "Not confirmed as printed"
+msgstr "尚未确认已打印"
+
+msgid "Once these labels have printed, confirm it here, so Kept stops counting them as unprinted."
+msgstr "这些标签打印完成后,请在此确认,这样 Kept 就不会再将它们计为未打印。"
+
+msgid "Each label: QR code and short ID. The codes are made when you print."
+msgstr "每张标签包含二维码和短 ID。编码在打印时生成。"
+
+msgid "Set aside a label sheet that was not printed"
+msgstr "暂缓一张未打印的标签纸"
+
+msgid "{bytes, plural, one {# byte} other {# bytes}}"
+msgstr "{bytes, plural, one {# 字节} other {# 字节}}"
+
+msgid "Nothing to download"
+msgstr "没有可下载的内容"
+
+msgid "No documents to download"
+msgstr "没有可下载的文档"
+
+msgid "Calculating the download size…"
+msgstr "正在计算下载大小…"
+
+msgid "What to label"
+msgstr "要打印标签的内容"
+
+msgid "Every place in here with no printed label, the ones never labelled too: each gets its ID now."
+msgstr "此处的每个未打印标签的位置(包括从未贴标的位置)现在都将分配编号。"
+
+msgid "Every thing in here with no printed label."
+msgstr "此处所有尚未打印标签的物品。"
+
+msgid "{name} now requires two-factor"
+msgstr "{name} 现已要求启用双重验证"
+
+msgid "{name} no longer requires two-factor"
+msgstr "{name} 已取消强制双重验证"
+
+msgid "Require two-factor for {name}?"
+msgstr "要求为 {name} 启用双重验证?"
+
+msgid "Members who haven't set up two-factor or a passkey can't open {name} until they do."
+msgstr "尚未设置双重验证或通行密钥的成员,在完成设置前将无法打开 {name}。"
+
+msgid "Not set up yet: {names}"
+msgstr "尚未设置:{names}"
+
+msgid "Everyone here has already set one up."
+msgstr "这里的每位成员都已设置。"
+
+msgid "Require two-factor"
+msgstr "强制要求双重验证"
+
+msgid "Stop requiring two-factor for {name}?"
+msgstr "停止强制 {name} 使用双重验证?"
+
+msgid "Members can open {name} with only their password again."
+msgstr "成员现在可以再次仅凭密码访问 {name}。"
+
+msgid "Stop requiring"
+msgstr "取消强制要求"
+
+msgid "On. Only the owner changes this."
+msgstr "已开启。仅所有者可更改此项。"
+
+msgid "Off. Only the owner changes this."
+msgstr "已关闭。仅拥有者可更改此项。"
+
+msgid "To ask everyone for two-factor, sign in with a passkey or your authenticator app first."
+msgstr "要向所有成员强制要求双重验证,请先使用通行密钥或验证器应用登录。"
+
+msgid "{0}, asks for two-factor"
+msgstr "{0},要求双重验证"
+
+msgid "{0}: asks for two-factor"
+msgstr "{0}:需要双重验证"
+
+msgid "<0>{name}0> asks for two-factor"
+msgstr "<0>{name}0> 要求使用双重验证"
+
+msgid "Turn on an authenticator app to open it, or add a passkey and sign in with it."
+msgstr "请启用验证器应用以打开它,或添加通行密钥并使用其登录。"
+
+msgid "Set up two-factor"
+msgstr "设置双重验证"
+
+msgid "Asks for two-factor: set it up to open it"
+msgstr "需要双重验证:请先设置后再打开"
+
+msgid "Nothing was imported, and no location was made."
+msgstr "未导入任何内容,也未创建任何空间。"
+
+msgid "What needed a look"
+msgstr "需要检查的内容"
+
+msgid "Imported, with a note"
+msgstr "已导入(附备注)"
+
+msgid "Item"
+msgstr "物品"
+
+msgid "Items with quantity 0"
+msgstr "数量为 0 的物品"
+
+msgid "Keep 0 or archive"
+msgstr "保留数量 0 或归档"
+
+msgid "Set to 1"
+msgstr "设为 1"
+
+msgid "{zeroItems, plural, one {# item has quantity 0.} other {# items have quantity 0.}}"
+msgstr "{zeroItems, plural, one {# 件物品数量为 0。} other {# 件物品数量为 0。}}"
+
+msgid "A type you run out of keeps 0; anything else comes in archived. The notes say \"Quantity in Homebox: 0\"."
+msgstr "会耗尽的消耗品类型会保留数量 0;其他物品将以已归档状态导入,备注中会注明「Homebox 中的数量:0」。"
+
+msgid "They come in as 1, and the notes say \"Quantity in Homebox: 0\"."
+msgstr "导入后数量将变为 1,并在备注中写明“Quantity in Homebox: 0”。"
+
+msgid "They aren't imported. What's inside one comes in, in its place."
+msgstr "这些分类不会作为实体导入,其中的物品会直接导入并保留其原有位置。"
+
+msgid "A new type"
+msgstr "新建类型"
+
+msgid "No type keeps things as they are, without a type's fields. A new type is made with the name you give it."
+msgstr "选「无类型」会保留物品原貌,不附加类型字段;选「新建类型」则会按你输入的名称创建新类型。"
+
+msgid "New type…"
+msgstr "新建类型…"
+
+msgid "Name of the new type"
+msgstr "新类型名称"
+
+msgid "Give the new type a name (at most {max} characters)."
+msgstr "为新类型命名(最多 {max} 个字符)。"
+
+msgid "Chosen"
+msgstr "已选"
+
+msgid "As boxes"
+msgstr "转为箱子"
+
+msgid "As places"
+msgstr "作为位置"
+
+msgid "These look like boxes"
+msgstr "这些位置看起来像箱子"
+
+msgid "Ticked, they come in as boxes: things that hold things, carried with what's inside. The rest come in as places. You can change either later."
+msgstr "勾选的项目将作为「收纳箱」(可随箱内物品一并搬动);其余则作为「位置」。导入后两者均可随时转换。"
+
+msgid "Choose none"
+msgstr "全不选"
+
+msgid "Choose all"
+msgstr "全选"
+
+msgid "{n} of {of} as boxes"
+msgstr "{n} / {of} 项作为收纳箱"
+
+msgid "Locations that look like boxes"
+msgstr "类似收纳箱的空间"
+
+msgid "Quantity 0 in Homebox; it came in as 1."
+msgstr "Homebox 中数量为 0;已按数量 1 导入。"
+
+msgid "Quantity 0 in Homebox, kept: its type is one you run out of."
+msgstr "Homebox 中数量为 0,已按 0 保留:其类型属于消耗品。"
+
+msgid "Quantity 0 in Homebox; it came in archived."
+msgstr "Homebox 中数量为 0;已按已归档状态导入。"
+
+msgid "Quantity 0 in Homebox, left out."
+msgstr "Homebox 中数量为 0,已略过。"
+
+msgid "It holds other items, so it came in as a box."
+msgstr "它内部装有其他物品,因此已作为箱子导入。"
+
+msgid "A location that came in as a box, as chosen."
+msgstr "按选择作为箱子导入的位置。"
+
+msgid "Its description isn't kept: places in Kept have no notes."
+msgstr "其描述不会保留:Kept 中的位置没有备注栏。"
+
+msgid "{joined}, and {more} more"
+msgstr "{joined} 等 {more} 项"
+
+msgid "Repaired the import"
+msgstr "已修复导入数据"
+
+msgid "Repair this import"
+msgstr "修复此导入"
+
+msgid "It was imported before Kept read Homebox the way it does now. Choose what to put right; one Undo takes it all back."
+msgstr "该数据是在 Kept 采用新版 Homebox 解析方式前导入的。请选择需要修正的内容;一次「撤销」即可全部还原。"
+
+msgid "{0, plural, one {Archive the # thing that had quantity 0 in Homebox} other {Archive the # things that had quantity 0 in Homebox}}"
+msgstr "{0, plural, one {归档 Homebox 中数量为 0 的 # 件物品} other {归档 Homebox 中数量为 0 的 # 件物品}}"
+
+msgid "<0>{0}0>: its things stop opening on an empty Contents tab. One that holds things stays a box."
+msgstr "<0>{0}0>:其中的物品将不再默认打开空的内容标签页。内部仍装有物品的将保持为箱子。"
+
+msgid "{0, plural, one {Make # type an ordinary type again} other {Make # types ordinary types again}}"
+msgstr "{0, plural, one {将 # 个类型还原为普通类型} other {将 # 个类型还原为普通类型}}"
+
+msgid "Rename <0>{0}0> to <1>{to}1>"
+msgstr "将 <0>{0}0> 重命名为 <1>{to}1>"
+
+msgid "Repair"
+msgstr "维修"
+
+msgid "Start with what you need; turn anything else on later in Location settings → What to track. Turning something off never deletes anything."
+msgstr "先从所需功能开始;之后随时可在“空间设置 → 追踪内容”中开启其他功能。关闭某项功能不会删除任何已有数据。"
+
+msgid "Repaired an import"
+msgstr "修复了一项导入"
+
+msgid "And what the backup uses"
+msgstr "同时也是备份所使用的密码"
+
+msgid "Turns on {name}"
+msgstr "将于 {name} 到期"
+
+msgid "{count, plural, one {Prices on # thing} other {Prices on # things}}"
+msgstr "{count, plural, one {包含 # 件物品的价格} other {包含 # 件物品的价格}}"
+
+msgid "{count, plural, one {# warranty} other {# warranties}}"
+msgstr "{count, plural, one {# 份保修} other {# 份保修}}"
+
+msgid "{count, plural, one {# maintenance entry} other {# maintenance entries}}"
+msgstr "{count, plural, one {# 条维护记录} other {# 条维护记录}}"
+
+msgid "What's unticked stays in the things' notes as text. Notes can't become records later: to keep it as records, tick it now."
+msgstr "未勾选的内容会以纯文本形式保留在物品备注中,且后续无法转换为独立记录。若需保留为结构化记录,请现在勾选。"
+
+msgctxt "sidebar group"
+msgid "Tracking"
+msgstr "追踪"
+
+msgid "Open {expected}"
+msgstr "打开 {expected}"
+
+msgid "This Kept is set up for <0>{expected}0>. Open it there."
+msgstr "此 Kept 实例配置的地址为 <0>{expected}0>。请从该地址打开。"
+
+msgid "This Kept is set up for a different address. Open it at the address you were given."
+msgstr "此 Kept 实例配置了其他访问地址。请使用提供给你的地址打开。"
+
+msgid "This Kept is set up for {address}. Open it there."
+msgstr "此 Kept 实例配置的地址为 {address}。请从该地址打开。"
+
+msgid "In Homebox, open Collection → Tools → Backup & Restore and choose Create Backup. When the backup is listed, Download it: that .zip is the file."
+msgstr "在 Homebox 中打开「Collection → Tools → Backup & Restore」,选择「Create Backup」。备份生成并列出后点击「Download」,得到的 .zip 即为备份文件。"
+
+msgid "Homebox v0.26.1 or newer (v0.27.0 recommended): Collection → Tools → Backup & Restore → Create Backup → Download. Older than v0.26: import its spreadsheet export, or update a copy of Homebox first."
+msgstr "Homebox v0.26.1 或更高版本(推荐 v0.27.0):Collection → Tools → Backup & Restore → Create Backup → Download。低于 v0.26 的版本请先导入其表格导出文件,或先升级 Homebox 副本。"
+
+msgid "On a home network without HTTPS, the person who runs this Kept can make one on the server: kept admin token create."
+msgstr "在没有 HTTPS 的家庭内网中,Kept 维护者可在服务器上运行命令生成密钥:kept admin token create。"
+
+msgid "Open the map"
+msgstr "打开平面图"
+
+msgid "Things: sort by"
+msgstr "物品排序方式"
+
+msgid "{count, plural, one {+# box} other {+# boxes}}"
+msgstr "{count, plural, one {+# 个箱子} other {+# 个箱子}}"
+
+msgid "Allow private addresses in Admin → Settings"
+msgstr "在「管理 → 设置」中允许私有内网地址"
+
+msgid "Passkeys need HTTPS. On a plain-HTTP address browsers don't offer them; put Kept on HTTPS to add one."
+msgstr "通行密钥需要 HTTPS。在明文 HTTP 地址下浏览器不会提供该功能;请将 Kept 部署在 HTTPS 后再添加。"
+
+msgid "{0, plural, one {secret value left out of the export} other {secret values left out of the export}}"
+msgstr "{0, plural, one {个私密字段值未包含在导出中} other {个私密字段值未包含在导出中}}"
+
+msgid "Staying on my home network"
+msgstr "仅在家庭网络内使用"
+
+msgid "Over plain HTTP, secret values stay out of the export. Each one is marked as left out, and the rest imports as usual."
+msgstr "在普通 HTTP 下,私密字段值不会包含在导出文件中。每处都会标记为已省略,其余内容正常导入。"
+
+msgid "Opening them needs HTTPS. Over plain HTTP everything else is imported without them; to bring them over too, import this file at Kept’s HTTPS address."
+msgstr "开启它们需要 HTTPS。在纯 HTTP 下,除这些项目外的其余内容均可正常导入;若要一并导入它们,请通过 Kept 的 HTTPS 地址执行导入。"
+
+msgid "{0} moved to {1} of {2}"
+msgstr "{0} 已移至 {2} 的 {1}"
+
+msgid "{count, plural, one {# chosen} other {# chosen}}"
+msgstr "{count, plural, one {已选 # 项} other {已选 # 项}}"
+
+msgid "{count, plural, one {Turn # place into a box} other {Turn # places into boxes}}"
+msgstr "{count, plural, one {将 # 个位置转为箱子} other {将 # 个位置转为箱子}}"
+
+msgid "{done, plural, one {Turned # place into a box} other {Turned # places into boxes}}"
+msgstr "{done, plural, one {已将 # 个位置转为箱子} other {已将 # 个位置转为箱子}}"
+
+msgid "A place"
+msgstr "位置"
+
+msgid "A to Z, numbers in order. Floors keep the order they were made in."
+msgstr "按 A–Z 及数字顺序排列。楼层则保留其创建顺序。"
+
+msgid "Choose places inside <0>{name}0> to turn into boxes. A box is a thing: it moves with everything in it. Each keeps its ID, its label and what's in it, and one Undo turns them all back."
+msgstr "选择 <0>{name}0> 内要转为箱子的位置。箱子属于一种物品,可连同内部物品一起移动。每个箱子都会保留原有的 ID、标签与存放内容,且支持一次撤销全部恢复。"
+
+msgid "Choose places inside it; one Undo turns them all back"
+msgstr "选择其中的位置;一次「撤销」即可全部还原"
+
+msgid "Custom order"
+msgstr "自定义顺序"
+
+msgid "It has places inside"
+msgstr "内部包含位置"
+
+msgid "It has places inside: move them out first"
+msgstr "其中还包含其他位置:请先将其移出"
+
+msgid "It is no longer in {0}"
+msgstr "它已不在 {0} 中"
+
+msgid "Move {0} down"
+msgstr "下移 {0}"
+
+msgid "Move {0} up"
+msgstr "上移 {0}"
+
+msgid "Move places up or down. Back to A to Z keeps this order for next time."
+msgstr "上下移动位置以调整顺序。点击「恢复按名称排序」后,下次也将保留该排序方式。"
+
+msgid "No places match"
+msgstr "没有匹配的位置"
+
+msgid "Order of the places here"
+msgstr "此处位置的排序"
+
+msgid "Order of the places in {0}"
+msgstr "{0} 中位置的排序"
+
+msgid "Order of the places inside"
+msgstr "内部位置的排序"
+
+msgid "Places inside"
+msgstr "内部位置"
+
+msgid "Places inside {0}"
+msgstr "{0} 内的位置"
+
+msgid "Put the places in {name} in a new order"
+msgstr "调整 {name} 中位置的排列顺序"
+
+msgid "Some places weren't turned into boxes"
+msgstr "部分位置未能转换为箱子"
+
+msgid "Turn places into boxes"
+msgstr "将位置转为箱子"
+
+msgid "Turn places into boxes…"
+msgstr "将位置转换为箱子…"
+
+msgid "Comes in, with a note"
+msgstr "按此方式导入,并添加备注"
+
+msgid "Left out: no item has a value for it."
+msgstr "已省略:没有任何物品包含此项值。"
+
+msgid "New type \"{typeName}\""
+msgstr "新类型「{typeName}」"
+
+msgid "Quantity 0 in Homebox; it comes in as 1."
+msgstr "Homebox 中数量为 0,导入后将设为 1。"
+
+msgid "Quantity 0 in Homebox; it comes in archived."
+msgstr "Homebox 中数量为 0;将按已归档状态导入。"
+
+msgid "It holds other items, so it comes in as a box."
+msgstr "它内部包含其他项目,因此将作为收纳箱导入。"
+
+msgid "A location that comes in as a box, as chosen."
+msgstr "按你的选择作为箱子导入的空间。"
+
+msgid "A location inside an item becomes a box."
+msgstr "物品内部的子位置将转为箱子。"
+
+msgid "A location inside an item became a box."
+msgstr "物品内部的子位置已转换为箱子。"
+
+msgid "Places keep their own order."
+msgstr "位置保持各自的排序。"
+
+msgid "Drag anything to move it. Drop small things on a counter, desk, shelf or box; wall things go on the nearest wall. To move a room, hold its floor, then drag. Drag its amber corner to resize it."
+msgstr "拖动任意元素即可移动。将小件物品放到台面、书桌、货架或箱子上;壁挂物品会自动吸附到最近的墙面。要移动房间,请按住地面拖动;拖动琥珀色角点可调整房间大小。"
+
+msgid "Rooms can’t overlap."
+msgstr "房间不能重叠。"
+
+msgid "Moved {room} up."
+msgstr "已将 {room} 上移。"
+
+msgid "Moved {room} down."
+msgstr "已将 {room} 下移。"
+
+msgid "Moved {room} left."
+msgstr "已将 {room} 向左移动。"
+
+msgid "Moved {room} right."
+msgstr "已将{room}向右移动。"
+
+msgid "Graph"
+msgstr "关系图"
+
+msgid "Selected"
+msgstr "已选择"
+
+msgid "{0} in <0>{1}0>"
+msgstr "{0}(位于 <0>{1}0>)"
+
+msgid "Tagged"
+msgstr "已添加分类标签"
+
+msgid "{0} inside"
+msgstr "内含 {0} 项"
+
+msgid "Inside it"
+msgstr "包含内容"
+
+msgid "Go in"
+msgstr "进入"
+
+msgid "Show on the map"
+msgstr "在平面图上显示"
+
+msgid "Graph of {0}"
+msgstr "{0} 的关系图"
+
+msgid "Rooms on no floor"
+msgstr "未归属楼层的房间"
+
+msgid "Stop turning"
+msgstr "停止旋转"
+
+msgid "Turn slowly"
+msgstr "缓慢转身"
+
+msgid "Look from higher"
+msgstr "俯视视角"
+
+msgid "Look from lower"
+msgstr "降低视角"
+
+msgid "Show the whole house"
+msgstr "显示全屋"
+
+msgid "The graph is drawn from Kept’s server. The list has everything offline."
+msgstr "图表数据由 Kept 服务器绘制。下方列表包含所有离线可用数据。"
+
+msgid "Where you are in the graph"
+msgstr "你在图谱中的当前位置"
+
+msgid "2D or 3D"
+msgstr "2D 或 3D"
+
+msgid "Size shows how much is inside. Pick twice to go in; the path above takes you back."
+msgstr "大小表示内部存放的物品数量。点击两次即可进入;点击上方的路径可返回。"
+
+msgid "It turns slowly until you touch it. Drag to turn it; pick a room to bring it forward."
+msgstr "在你操作前它会缓缓旋转。拖动即可旋转视角;点击某个房间可将其拉近展示。"
+
+msgid "{more, plural, one {# more thing is counted in its place but not drawn.} other {# more things are counted in their places but not drawn.}}"
+msgstr "{more, plural, one {另有 # 件物品已计入对应位置但未绘制。} other {另有 # 件物品已计入对应位置但未绘制。}}"
+
+msgid "In this graph"
+msgstr "在此关系图中"
+
+msgid "In <0>{0}0>"
+msgstr "位于 <0>{0}0>"
+
+msgid "low on stock"
+msgstr "库存不足"
+
+msgid "lent out"
+msgstr "已借出"
+
+msgid "due soon"
+msgstr "即将到期"
+
+msgid "{count, plural, one {# low on stock} other {# low on stock}}"
+msgstr "{count, plural, one {# 项库存不足} other {# 项库存不足}}"
+
+msgid "{count, plural, one {# lent out} other {# lent out}}"
+msgstr "{count, plural, one {# 件已借出} other {# 件已借出}}"
+
+msgid "{count, plural, one {# due soon} other {# due soon}}"
+msgstr "{count, plural, one {# 项即将到期} other {# 项即将到期}}"
+
+msgid "{count, plural, one {# more in {where}} other {# more in {where}}}"
+msgstr "{count, plural, one {{where} 中还有 # 项} other {{where} 中还有 # 项}}"
+
+msgid "graph"
+msgstr "图表"
+
+msgid "Add a label code"
+msgstr "添加标签编码"
+
+msgid "Scan a blank label you've stuck on it"
+msgstr "扫描已贴在上面的空白标签"
+
+msgid "Attach to an existing place"
+msgstr "附着到现有位置"
+
+msgid "Attach to <0>{0}0>"
+msgstr "附加到 <0>{0}0>"
+
+msgid "A room, shelf or spot"
+msgstr "房间、货架或点位"
+
+msgid "Claimed for <0>{label}0> on this phone, until it syncs."
+msgstr "已在此手机上认领标签 <0>{label}0>,待同步后生效。"
+
+msgid "Claimed for <0>{label}0>."
+msgstr "已为 <0>{label}0> 发起理赔。"
+
+msgid "Blank label {code}"
+msgstr "空白标签 {code}"
+
+msgid "Not matched: {text}"
+msgstr "未匹配:{text}"
+
+msgid "Check later: {text}"
+msgstr "稍后核对:{text}"
+
+msgid "Delete this service?"
+msgstr "要删除此维护项目吗?"
+
+msgid "Edit the service"
+msgstr "编辑服务"
+
+msgid "Its lines and invoice go too. Schedules it completed count from the service before. You can undo this."
+msgstr "对应的明细和发票也会一并删除,已完成的计划将回退至前一次维护记录起算。此操作可撤销。"
+
+msgid "Logged by"
+msgstr "记录人"
+
+msgid "They have prices you can't see, so they stay as they are."
+msgstr "它们包含你无权查看的价格信息,因此保持原样。"
+
+msgid "Check that a code on the sheets scans. Yes records today as their print date, so the boxes show their label."
+msgstr "请确认纸张上的二维码可以正常扫描。选“是”会将今天记录为打印日期,箱子也会显示对应的标签。"
+
+msgid "A sold date with no buyer or price isn't a sale: it stays in use, with the date in its notes."
+msgstr "只有售出日期而没有买家或价格不算售出:物品将保留为在用状态,该日期会记入备注。"
+
+msgid "{0, plural, one {Put the # thing marked sold on a date alone back in use} other {Put the # things marked sold on a date alone back in use}}"
+msgstr "{0, plural, one {将仅按日期标记为已售出的 # 件物品恢复为在用状态} other {将仅按日期标记为已售出的 # 件物品恢复为在用状态}}"
+
+msgid "Add “{typed}”"
+msgstr "添加「{typed}」"
+
+msgid "Chapters done"
+msgstr "已完成章节"
+
+msgid "Done ({done})"
+msgstr "已完成({done})"
+
+msgid "One chapter per section. Tap one to start there."
+msgstr "每个板块对应一节,轻点即可从该处开始。"
+
+msgid "Move it, lend it, print its label or move it to the Trash."
+msgstr "移动、借出、打印标签,或移入回收站。"
+
+msgid "Details, paperwork, history and the rest, each in its own tab. Tap a photo to see it full screen."
+msgstr "详情、文档资料、历史记录等内容各自独立分页。轻点照片可全屏查看。"
+
+msgid "List, Grid, Graph or Map"
+msgstr "列表、网格、关系图或平面图"
+
+msgid "Pick how this location is shown. Graph shows what's inside what; Map draws it floor by floor."
+msgstr "选择此空间的展示方式。关系图展示层级包含关系;平面图按楼层绘制空间布局。"
+
+msgid "List, Grid, Graph, Table or Map"
+msgstr "列表、网格、关系图、表格或平面图"
+
+msgid "Pick how this location is shown. Table, on a wide screen, works like a spreadsheet."
+msgstr "选择此空间的展示方式。在宽屏设备上,表格视图操作起来就像电子表格。"
+
+msgid "Graph, in 2D or 3D"
+msgstr "2D 或 3D 关系图"
+
+msgid "Floors, rooms, boxes and things as a graph. Pick one for its card, pick it again to go in."
+msgstr "以关系图形式查看楼层、房间、箱子和物品。点一下查看卡片,再点一下进入详情。"
+
+msgid "Draw rooms and add a floor. Drag a room to move it, with everything in it."
+msgstr "绘制房间并添加楼层。拖动房间可连同其中所有物品一并移动。"
+
+msgid "Select several"
+msgstr "多选"
+
+msgid "Select things in a list to move them, print their labels or move them to the Trash."
+msgstr "在列表中选择多个物品,即可批量移动、打印标签或移入回收站。"
+
+msgid "Print a sheet for everything still without a label, or a blank sheet to name later."
+msgstr "为所有尚未贴标签的物品打印一张标签纸,或打印空白标签纸以便日后命名。"
+
+msgid "Point the camera at a label to open what it's on. A blank one can go on a thing or place you have."
+msgstr "将摄像头对准标签即可打开对应页面。空白标签可贴在你现有的物品或位置上。"
+
+msgid "Every service with what it cost. Tap one to open all of it, with its invoice."
+msgstr "列出每次维护保养及其费用。轻点任意一项即可查看完整详情与发票。"
+
+msgid "Graph & 3D map"
+msgstr "关系图与 3D 平面图"
+
+msgid "Play"
+msgstr "播放"
+
+msgid "Slide {n} of {total}: {title}"
+msgstr "第 {n} / {total} 张:{title}"
+
+msgid "Slide {n} of {total}"
+msgstr "第 {n} / {total} 张"
+
+msgid "What's new in Kept"
+msgstr "Kept 更新日志"
+
+msgid "Version <0>{version}0>"
+msgstr "版本 <0>{version}0>"
+
+msgid "The release notes are in English."
+msgstr "更新说明为英文。"
+
+msgid "Full release notes"
+msgstr "完整发布说明"
+
+msgid "Version <0>{version}0>: its highlights."
+msgstr "版本 <0>{version}0>:更新亮点。"
+
+msgid "Highlights"
+msgstr "亮点"
+
+msgid "{across} × {up} cubes"
+msgstr "{across} × {up} 格"
+
+msgid "{across} across, {up} up, counted from the top left, row by row"
+msgstr "每行 {across} 枚、每列 {up} 枚,从左上角起逐行计数"
+
+msgid "{code} doesn't follow this location's code rule: {message}"
+msgstr "{code} 不符合此空间的编码规则:{message}"
+
+msgid "{code} doesn't follow this location's code rule."
+msgstr "{code} 不符合此空间的编码规则。"
+
+msgid "{code} is already on something else here."
+msgstr "{code} 已被此空间的其他项目使用。"
+
+msgid "{code} would be on two places. Change the code pattern."
+msgstr "{code} 会同时落在两个位置上,请修改编号规则。"
+
+msgid "{inside, plural, one {With # place inside} other {With # places inside}}"
+msgstr "{inside, plural, one {内含 # 个位置} other {内含 # 个位置}}"
+
+msgid "{count, plural, one {# shelf} other {# shelves}}"
+msgstr "{count, plural, one {# 个货架} other {# 个货架}}"
+
+msgid "{count, plural, one {# drawer} other {# drawers}}"
+msgstr "{count, plural, one {# 个抽屉} other {# 个抽屉}}"
+
+msgid "{N} is the number, {ROW} and {COL} where it sits."
+msgstr "{N} 为编号,{ROW} 和 {COL} 为所在行列位置。"
+
+msgid "{PARENT} is its own code; {PADDED} pads to two digits."
+msgstr "{PARENT} 为父级自身的编号;{PADDED} 会补齐至两位数字。"
+
+msgid "A grid is 1 to {side} across and up, at most {most} cubes; shelves and drawers 1 to {count}."
+msgstr "网格横向和纵向均为 1 至 {side} 格,最多 {most} 个格子;层板与抽屉数量为 1 至 {count}。"
+
+msgid "Across"
+msgstr "横向"
+
+msgid "Add furniture to {hereName}"
+msgstr "向 {hereName} 添加家具"
+
+msgid "Bookcase"
+msgstr "书柜"
+
+msgid "Built in: {builtins}."
+msgstr "内置:{builtins}。"
+
+msgid "Choose 1 to {max}."
+msgstr "选择 1 到 {max} 项。"
+
+msgid "Compartment codes (optional)"
+msgstr "分格编码(可选)"
+
+msgid "Compartment names"
+msgstr "分格名称"
+
+msgid "Compartments"
+msgstr "隔层"
+
+msgid "Cube"
+msgstr "立方格"
+
+msgid "Cube {n}"
+msgstr "格 {n}"
+
+msgid "Cube shelf {across} × {up}"
+msgstr "方格架 {across} × {up}"
+
+msgid "Cubes"
+msgstr "格数"
+
+msgid "Drawer"
+msgstr "抽屉"
+
+msgid "Drawer {n}"
+msgstr "第 {n} 格抽屉"
+
+msgid "Drawers"
+msgstr "抽屉柜"
+
+msgid "Edit place template"
+msgstr "编辑位置模板"
+
+msgid "Furniture already made from it stays as it is."
+msgstr "已经基于它创建的家具将保持不变。"
+
+msgid "Furniture with compartments…"
+msgstr "带隔层的家具…"
+
+msgid "Give it a name, like Cube shelf 01."
+msgstr "起个名称,例如“方格柜 01”。"
+
+msgid "Give it a name, like Wide cube shelf."
+msgstr "输入名称,例如“宽格子柜”。"
+
+msgid "Give the furniture its own code first: these codes start with it."
+msgstr "请先为该家具设置编码:各格位编码将以其作为前缀。"
+
+msgid "How it stands"
+msgstr "当前状态"
+
+msgid "Its own code (optional)"
+msgstr "自带编码(可选)"
+
+msgid "Kind of each compartment"
+msgstr "每个隔层的类型"
+
+msgid "Kind of the furniture"
+msgstr "家具类型"
+
+msgid "Make one for furniture you have more than one of, with its compartments, their names and their codes."
+msgstr "为同款多件家具创建模板,预设格位、名称与编码规则。"
+
+msgid "Members of these locations can make furniture from it."
+msgstr "这些空间的成员可使用此模板创建家具。"
+
+msgid "New place template"
+msgstr "新建位置模板"
+
+msgid "No place templates of your own yet"
+msgstr "你还没有自定义位置模板"
+
+msgid "On its side"
+msgstr "侧面平放"
+
+msgid "Place templates"
+msgstr "位置模板"
+
+msgid "Search place templates"
+msgstr "搜索位置模板"
+
+msgid "Shelf"
+msgstr "层架"
+
+msgid "Shelf {n}"
+msgstr "第 {n} 层搁板"
+
+msgid "Shelving unit"
+msgstr "置物架"
+
+msgid "Template"
+msgstr "模板"
+
+msgid "Templates for"
+msgstr "适用模板:"
+
+msgid "Up, standing upright"
+msgstr "向上,直立摆放"
+
+msgid "Upright"
+msgstr "立放"
+
+msgid "Use {N} for the number, or {ROW} and {COL}."
+msgstr "使用 {N} 表示编号,或使用 {ROW} 和 {COL}。"
+
+msgid "Use {N}, or {ROW} and {COL}, so each one gets its own code."
+msgstr "使用 {N},或 {ROW} 与 {COL},以便每个位置获得独立编号。"
+
+msgid "Couldn't change its kind"
+msgstr "无法更改位置类型"
+
+msgid "Kind of {title}"
+msgstr "{title} 的类型"
+
+msgid "Paperless document changed"
+msgstr "Paperless 文档已更改"
+
+msgid "Read a floor plan"
+msgstr "识别平面图"
+
+msgid "Discarded a floor plan"
+msgstr "已放弃平面图"
+
+msgid "{count, plural, one {Added # room from a floor plan} other {Added # rooms from a floor plan}}"
+msgstr "{count, plural, one {已从平面图添加 # 个房间} other {已从平面图添加 # 个房间}}"
+
+msgid "Floor plans"
+msgstr "平面图"
+
+msgid "{n, plural, one {Added # room from the plan} other {Added # rooms from the plan}}"
+msgstr "{n, plural, one {已从平面图添加 # 个房间} other {已从平面图添加 # 个房间}}"
+
+msgid "Someone arranged this map since you started. Load it again; your rooms stay to add."
+msgstr "在你开始编辑后,其他人已调整过此平面图。请重新加载;你待添加的房间会保留。"
+
+msgid "Discard this plan?"
+msgstr "放弃此平面图?"
+
+msgid "Nothing is added. The plan is deleted."
+msgstr "未添加任何内容,平面图已删除。"
+
+msgid "Couldn’t read this plan."
+msgstr "无法读取此平面图。"
+
+msgid "Dashed rooms are from the plan and not added yet. Drag to move one; drag its corner to resize it."
+msgstr "虚线房间识别自平面图,尚未正式添加。拖动可移动位置,拖动边角可调整大小。"
+
+msgid "{0, plural, one {Add # room} other {Add # rooms}}"
+msgstr "{0, plural, one {添加 # 个房间} other {添加 # 个房间}}"
+
+msgid "Show the plan"
+msgstr "显示平面图"
+
+msgid "Turn the rooms"
+msgstr "旋转房间"
+
+msgid "From a plan"
+msgstr "来自平面图"
+
+msgid "<0>{room}0>, from the plan, not added, {w} by {d} metres"
+msgstr "<0>{room}0>,来自平面图,尚未添加,{w} × {d} 米"
+
+msgid "No rooms on the map yet"
+msgstr "平面图上暂无房间"
+
+msgid "Start from a floor plan, or draw the rooms yourself."
+msgstr "从平面图开始,或自己绘制房间。"
+
+msgid "Start from a floor plan"
+msgstr "从平面图开始"
+
+msgid "For a PDF, try a screenshot of the plan."
+msgstr "如果是 PDF 平面图,请先截图后再上传。"
+
+msgid "This doesn’t look like a floor plan."
+msgstr "这张图片看起来不像平面图。"
+
+msgid "No rooms found on this plan."
+msgstr "未在此平面图上识别到房间。"
+
+msgid "Draw rooms yourself"
+msgstr "手动绘制房间"
+
+msgid "A floor plan is ready to check."
+msgstr "平面图已识别完成,待核对。"
+
+msgid "Check it"
+msgstr "立即检查"
+
+msgid "Reading the plan…"
+msgstr "正在识别平面图…"
+
+msgid "You can leave; the plan waits on the map."
+msgstr "你可以先离开,平面图会保留在地图上。"
+
+msgid "<0>{room}0> is…"
+msgstr "<0>{room}0> 是…"
+
+msgid "Width (m)"
+msgstr "宽度(米)"
+
+msgid "Depth (m)"
+msgstr "进深 (m)"
+
+msgid "Rescale"
+msgstr "重新校准比例"
+
+msgid "Scale from {room}’s size"
+msgstr "按{room}尺寸缩放"
+
+msgid "Sizes from the plan: {n} of {m} rooms agree"
+msgstr "平面图尺寸校验:{n} / {m} 个房间尺寸一致"
+
+msgid "Scale from the plan’s scale bar"
+msgstr "根据平面图的比例尺换算"
+
+msgid "Scale from the doors, taken as 80 cm wide: check one room"
+msgstr "按门宽 80 厘米推算比例:请核对一个房间"
+
+msgid "No sizes on the plan: these are a guess"
+msgstr "平面图未标注尺寸:以下为估算值"
+
+msgid "Rooms from the plan"
+msgstr "平面图中的房间"
+
+msgid "Set a room’s size"
+msgstr "设置房间尺寸"
+
+msgid "Kept read the first 60 rooms. Add the rest by drawing."
+msgstr "Kept 读取了前 60 个房间,其余房间请手动绘制添加。"
+
+msgid "Keep the plan with <0>{location}0>"
+msgstr "将平面图保留在 <0>{location}0> 中"
+
+msgid "A new floor"
+msgstr "新楼层"
+
+msgid "Already on the map."
+msgstr "已在平面图上。"
+
+msgid "Uses your <0>{existing}0>"
+msgstr "使用你现有的 <0>{existing}0>"
+
+msgid "Make a new room"
+msgstr "创建新房间"
+
+msgid "Not a rectangle: drawn as its largest part."
+msgstr "非矩形区域:按其最大部分绘制。"
+
+msgid "The plan says <0>{size}0>."
+msgstr "平面图尺寸为 <0>{size}0>。"
+
+msgid "Name unclear on the plan."
+msgstr "平面图上的名称不够清晰。"
+
+msgid "Add {room}"
+msgstr "添加{room}"
+
+msgid "A photo, a screenshot or a PDF of a plan. Kept reads the rooms and their sizes; you check them before anything is added."
+msgstr "平面图的照片、截图或 PDF。Kept 会识别房间及其尺寸;在正式添加前你可以逐一核对。"
+
+msgid "Use a sample floor plan"
+msgstr "使用示例平面图"
+
+msgid "Choose a file"
+msgstr "选择文件"
+
+msgid "The plan you chose"
+msgstr "你选择的平面图"
+
+msgid "Turn the plan a quarter turn"
+msgstr "将平面图旋转 90 度"
+
+msgid "Only the first page is read."
+msgstr "仅读取第一页。"
+
+msgid "Up to ~{tokens} tokens"
+msgstr "最高约 {tokens} tokens"
+
+msgid "Kept sends the plan, without its location data, to <0>{name}0>. It is deleted when you finish, unless you keep it."
+msgstr "Kept 会将不含空间数据的平面图发送给 <0>{name}0>。除非你选择保留,否则完成后会自动删除。"
+
+msgid "Read the plan"
+msgstr "识别平面图"
+
+msgid "Someone else added or discarded this plan."
+msgstr "其他人已添加或放弃此平面图。"
+
+msgid "Fold all"
+msgstr "全部折叠"
+
+msgid "Open all"
+msgstr "全部打开"
+
+msgid "Set up by a Home Assistant administrator"
+msgstr "由 Home Assistant 管理员设置"
+
+msgid "Your setup code is on the app's Log tab in Home Assistant."
+msgstr "你的配置码位于 Home Assistant 中该应用的「日志 (Log)」标签页。"
+
+msgid "Running as a Home Assistant app"
+msgstr "正在作为 Home Assistant 应用运行"
+
+msgid "Not saved yet"
+msgstr "尚未保存"
+
+msgid "{0}, change the type"
+msgstr "{0},更改类型"
+
+msgid "Choose a type"
+msgstr "选择类型"
+
+msgid "Couldn't save the label image. Try again."
+msgstr "无法保存标签图片,请重试。"
+
+msgid "Kept label"
+msgstr "Kept 标签"
+
+msgid "Loading the label"
+msgstr "正在加载标签"
+
+msgid "Saved the label image"
+msgstr "已保存标签图片"
+
+msgid "Show the label"
+msgstr "显示标签"
+
+msgid "The label as it prints: {0}"
+msgstr "实际打印的标签:{0}"
+
+msgid "The new type's own fields show after you save."
+msgstr "保存后将显示新类型的专属字段。"
+
+msgctxt "printed label"
+msgid "Label"
+msgstr "标签"
+
+msgid "What the file can hold"
+msgstr "文件容量上限"
+
+msgid "The first row names the columns, in any of Kept's languages. Kept matches the names it knows, and you choose the rest in the next step. Only a name is needed."
+msgstr "第一行应为各列名称,支持 Kept 的任意界面语言。Kept 会自动匹配已知列名,其余列可在下一步手动指定。仅「名称」为必填。"
+
+msgid "The columns Kept reads"
+msgstr "Kept 识别的列"
+
+msgid "A field of your own types, such as Wattage"
+msgstr "你自定义的类型的字段,例如“功率”"
+
+msgid "Place: from the top down, separated by >, like Garage > Shelf A. Another separator can be chosen."
+msgstr "位置:按从大到小的层级排列并用 > 分隔,例如「车库 > A 货架」。也可以选择其他分隔符。"
+
+msgid "Tags and other names: separated by commas."
+msgstr "分类标签与其他名称:用逗号分隔。"
+
+msgid "Dates: written the same way all through the file, like 2026-10-29 or 29/10/2026."
+msgstr "日期:整个文件中的写法统一,例如 2026-10-29 或 29/10/2026。"
+
+msgid "Prices: a number, without the currency sign."
+msgstr "价格:纯数字,不含货币符号。"
+
+msgid "Download a sample CSV"
+msgstr "下载示例 CSV"
+
+msgid "How importing works"
+msgstr "导入说明"
+
+msgid "Turn on {label} here"
+msgstr "在此开启 {label}"
+
+msgid "{label} is on in {0}"
+msgstr "{label} 已在 {0} 开启"
+
+msgid "Ask {who} to turn it on."
+msgstr "请 {who} 开启此功能。"
+
+msgid "Turn it on where you lend or borrow things: who has what, and when it's due back. Nothing else changes."
+msgstr "在需要借出或借入物品的空间开启:记录谁借走了什么以及何时应归还,其他设置不变。"
+
+msgid "<0>{name}0> is yours alone: it has no members, invites or share links. Move a thing into a shared home when it becomes shared."
+msgstr "<0>{name}0> 仅属于你个人:不包含成员、邀请或分享链接。当物品需要与他人共用时,可将其移入共享空间。"
+
+msgid "<0>{personal}0> with its files, your profile and preferences, and the AI calls you made. Locations you own are exported one by one."
+msgstr "<0>{personal}0> 及其附件、你的个人资料与偏好设置,以及你的 AI 调用记录。你拥有的空间需逐个单独导出。"
+
+msgid "<0>{personal}0>, your own location, is ready for what's on you: keys, wallet, phone. Now add the place you live. It comes with the usual rooms, and you can change them."
+msgstr "你的专属空间 <0>{personal}0> 已就绪,可用来记录随身物品(钥匙、钱包、手机等)。现在添加你的居住空间吧,系统会预设常用房间,你也可以随时修改。"
+
+msgid "<0>{personal}0>, your own location, tracks the same from when the import runs. The menu shows what any of your locations tracks."
+msgstr "你的个人空间 <0>{personal}0> 将在导入运行起同步开启相同的追踪项目。菜单中会显示各空间当前开启的项目。"
+
+msgid "<0>{personal}0>, your profile and preferences, and your AI calls, as one file."
+msgstr "将 <0>{personal}0>、你的个人资料与偏好设置以及 AI 调用记录打包为一个文件。"
+
+msgid "<0>{personal}0>, your profile and preferences, as one file."
+msgstr "<0>{personal}0>、你的个人资料与偏好设置,合并导出为单个文件。"
+
+msgid "After 30 days, with <0>{personal}0>. You can keep it until then."
+msgstr "30 天后与 <0>{personal}0> 一并删除。在此之前你可以随时保留账号。"
+
+msgid "Also for <0>{personal}0>"
+msgstr "同时应用于 <0>{personal}0>"
+
+msgid "This key pays for all of <0>{ownerName}0>'s homes: <1>{list}1>. <2>{personal}2> uses your personal key if you add one."
+msgstr "此密钥用于支付 <0>{ownerName}0> 名下的所有空间:<1>{list}1>。若你添加了个人密钥,<2>{personal}2> 将改用你的个人密钥。"
+
+msgid "Used for <0>{personal}0>, your private threads, and questions that span owners."
+msgstr "用于 <0>{personal}0>、你的私密对话,以及跨拥有者的提问。"
+
+msgid "You asked for it, with your own location and everything in it. Until then nothing else in Kept opens. Keep the account to go back to it as it was."
+msgstr "你已申请删除账号及名下个人空间和所有内容。在此期间 Kept 中的其他内容均无法打开。选择“保留账号”即可恢复原状。"
+
+msgid "Your account, your own location <0>{personal}0> and everything in it are deleted 30 days from now. Until then you can sign in and keep the account; nothing else opens."
+msgstr "你的账号、个人空间 <0>{personal}0> 及其中所有内容将在 30 天后永久删除。在此之前你仍可登录并保留账号,其他功能将无法打开。"
+
+msgid "Your own key is for <0>{personal}0>, your private threads, and questions that span owners."
+msgstr "你自己的密钥用于 <0>{personal}0>、你的私人对话,以及跨所有者的问题。"
+
+msgid "{0, plural, one {# location searches by name only} other {# locations search by name only}}"
+msgstr "{0, plural, one {# 个空间仅按名称搜索} other {# 个空间仅按名称搜索}}"
+
+msgid "{providerName} has no embeddings model, so search can't match by meaning: \"laptop\" won't find a MacBook Pro. Search by meaning needs a provider with one, such as OpenAI or Google, chosen under Advanced."
+msgstr "{providerName} 没有向量嵌入模型,因此搜索无法按语义匹配:搜“笔记本电脑”将找不到 MacBook Pro。语义搜索需要带有嵌入模型的服务商(例如 OpenAI 或 Google),可在“高级”中选择。"
+
+msgid "Choose a Search model"
+msgstr "选择 Search 模型"
+
+msgid "Choose another provider"
+msgstr "选择其他服务商"
+
+msgid "No Search model is chosen, so search can't match by meaning: \"laptop\" won't find a MacBook Pro. Choose one under Advanced → Models."
+msgstr "未选择搜索向量模型,因此搜索无法按语义匹配:例如搜“笔记本电脑”将无法找到 MacBook Pro。请在“高级 → 模型”中选择一个模型。"
+
+msgid "Search matches names only"
+msgstr "搜索仅匹配名称"
+
+msgid "Searched by name only: no embeddings model is set, so \"laptop\" won't find a MacBook Pro. <0>Settings → AI0>"
+msgstr "仅按名称搜索:未配置向量嵌入模型,因此搜“笔记本电脑”不会匹配到 MacBook Pro。<0>设置 → AI0>"
+
+msgid "Their AI has no embeddings model, so \"laptop\" won't find a MacBook Pro. Each owner chooses a Search model in Settings → AI → Advanced; a Search model on this server's key covers every location without one."
+msgstr "他们的 AI 未配置向量模型,因此搜索“笔记本电脑”无法匹配到 MacBook Pro。每位所有者可在「设置 → AI → 高级」中选择搜索模型;在此服务器密钥上配置的搜索模型将覆盖所有未单独设置的空间。"
+
+msgid "Date format"
+msgstr "日期格式"
+
+msgctxt "date format"
+msgid "Default"
+msgstr "默认"
+
+msgid "Default leaves the year off this year’s dates. Purchase and warranty dates always show it."
+msgstr "默认隐藏今年日期中的年份。购买日期与保修日期始终显示完整年份。"
+
+msgid "How dates and times are written in English."
+msgstr "英文中日期和时间的书写格式。"
+
+msgid "United Kingdom"
+msgstr "英国"
+
+msgid "United States"
+msgstr "美国"
+
+msgid "Name {title}"
+msgstr "命名 {title}"
+
+msgid "Name cleared"
+msgstr "已清除名称"
+
+msgid "Named {0}"
+msgstr "已命名为 {0}"
+
+msgid "What it is, e.g. Insurance 2026. Leave it empty to show its kind."
+msgstr "文档名称,例如“2026 房屋保险”。留空则直接显示文档类型。"
+
+msgid "{others, plural, one {This receipt has # other thing on it: the date and shop change for it too.} other {This receipt has # other things on it: the date and shop change for them too.}}"
+msgstr "{others, plural, one {此收据上还包含另外 # 件物品:更改日期和商店也会一并影响它。} other {此收据上还包含另外 # 件物品:更改日期和商店也会一并影响它们。}}"
+
+msgid "Add a receipt"
+msgstr "添加收据"
+
+msgid "Add the purchase"
+msgstr "添加购买记录"
+
+msgid "Add the purchase of {0}"
+msgstr "添加 {0} 的采购记录"
+
+msgid "Choose the day it was bought."
+msgstr "选择购买日期。"
+
+msgid "Edit the purchase"
+msgstr "编辑购买记录"
+
+msgid "No purchase recorded: when and where it was bought, and what it cost."
+msgstr "尚未记录购买信息:购买时间、商家和价格。"
+
+msgid "Price of one"
+msgstr "单价"
+
+msgid "Purchase of {0}"
+msgstr "购买 {0}"
+
+msgid "Purchase saved"
+msgstr "采购记录已保存"
+
+msgid "These are the purchase’s receipts: every thing bought on it shows them. A receipt added under Paperwork is this thing’s own and shows only there."
+msgstr "这些是该笔购买的通用收据:同笔购买中的所有物品都会显示它们。而在「文档与单据」下添加的收据仅属于当前物品,且只在此处显示。"
+
+msgid "This purchase is kept in another location; change it there."
+msgstr "此购买记录保存在另一个空间中;请在那个空间里修改。"
+
+msgid "Also in Paperwork"
+msgstr "同时存在于文档资料中"
+
+msgid "At most 300 characters."
+msgstr "最多 300 个字符。"
+
+msgid "Couldn't change the receipt"
+msgstr "无法更改收据"
+
+msgid "How the receipt names it."
+msgstr "收据上的品名。"
+
+msgid "It comes off the purchase. The file itself stays until it's purged."
+msgstr "仅从该采购记录中移除关联,文件本身会保留直至被彻底清理。"
+
+msgid "Its date, shop, price and receipts go. The thing stays."
+msgstr "购买日期、商家、价格与收据将被删除,物品本身保留。"
+
+msgid "Left empty, it is the price times the quantity."
+msgstr "留空则按单价乘以数量计算。"
+
+msgid "No receipt yet."
+msgstr "暂无收据。"
+
+msgid "Purchase notes"
+msgstr "购买备注"
+
+msgid "Purchase removed"
+msgstr "已移除购买记录"
+
+msgid "Receipt replaced"
+msgstr "收据已替换"
+
+msgid "Receipt total"
+msgstr "收据总额"
+
+msgid "Remove {0}?"
+msgstr "移除 {0}?"
+
+msgid "Remove {label}"
+msgstr "移除 {label}"
+
+msgid "Remove this purchase?"
+msgstr "移除此采购记录?"
+
+msgid "Take {0} off this receipt?"
+msgstr "从这张收据中移除 {0}?"
+
+msgid "Take it off"
+msgstr "移除"
+
+msgid "Taken off the receipt"
+msgstr "已从收据移除"
+
+msgid "The receipt and its other things stay as they are."
+msgstr "该收据及其中的其他物品保持不变。"
+
+msgid "As you face it."
+msgstr "正面朝向你时。"
+
+msgid "Choose compartments side by side to merge them, or one merged compartment to split it again."
+msgstr "选择相邻的分格进行合并,或选择一个已合并的分格将其重新拆分。"
+
+msgid "Compartments after turning"
+msgstr "旋转后的分格方向"
+
+msgid "Each gets the number and code of where it now stands, top left first. An old code opens the compartment now in its place; printed labels stay with theirs."
+msgstr "按从上到下、从左到右的顺序为各格位分配编号与当前位置编码。旧编码会打开现在位于该位置的格位;已打印的标签仍保留原格位对应关系。"
+
+msgid "Its compartments"
+msgstr "其分格"
+
+msgid "Its top went"
+msgstr "顶部朝向"
+
+msgid "Keep the codes"
+msgstr "保留原有编号"
+
+msgid "Merge or split…"
+msgstr "合并或拆分…"
+
+msgid "Merged compartments of {name}"
+msgstr "已合并 {name} 的格位"
+
+msgid "Merged into {merged}"
+msgstr "已合并到 {merged}"
+
+msgid "Only how it stands changes: each keeps its number, name and codes."
+msgstr "仅变更摆放朝向:每个房间仍保留各自的编号、名称和编码。"
+
+msgid "Print their labels"
+msgstr "打印它们的标签"
+
+msgid "Renumber"
+msgstr "重新编号"
+
+msgid "Renumbered. Print their labels again for the new names."
+msgstr "已重新编号。请重新打印标签以更新名称。"
+
+msgid "Split a compartment of {name}"
+msgstr "拆分 {name} 的隔层"
+
+msgid "The numbers and codes are as they were."
+msgstr "编号与编码保持原样。"
+
+msgid "To the left"
+msgstr "左侧"
+
+msgid "To the right"
+msgstr "朝右"
+
+msgid "Top to the left"
+msgstr "顶部朝左"
+
+msgid "Top to the right"
+msgstr "顶部朝右"
+
+msgid "Turn {unit}"
+msgstr "旋转 {unit}"
+
+msgid "Turn it…"
+msgstr "将其转换为…"
+
+msgid "Turned {unit}"
+msgstr "已转换 {unit}"
+
+msgid "Length"
+msgstr "长度"
+
+msgid "A room is at least {min} m across."
+msgstr "房间宽度至少为 {min} 米。"
+
+msgid "A room is at most {max} m across."
+msgstr "房间单边最长为 {max} 米。"
+
+msgid "Give the width and the length, or neither."
+msgstr "请同时填写宽度和长度,或两者都留空。"
+
+msgid "On the map at its size."
+msgstr "按实际尺寸显示在平面图上。"
+
+msgid "Size on the map"
+msgstr "平面图上的尺寸"
+
+msgid "Optional, to the centimetre. Leave it empty and the map sizes the room itself."
+msgstr "选填,精确到厘米。留空则由平面图自动估算房间尺寸。"
+
+msgid "Under 50 cm: too small for the map."
+msgstr "小于 50 cm:太小了,无法在平面图上显示。"
+
+msgid "Decrease {label}"
+msgstr "减少 {label}"
+
+msgid "Increase {label}"
+msgstr "增加{label}"
+
+msgid "Enter metres, like {example}."
+msgstr "请输入米数,例如 {example}。"
+
+msgid "Enter a whole number."
+msgstr "请输入整数。"
+
+msgid "The new receipt is added, but the old one couldn't be removed"
+msgstr "新收据已添加,但无法移除旧收据"
+
+msgid "Sign-in length"
+msgstr "登录时长"
+
+msgid "Renewed as it is used."
+msgstr "使用期间自动续期。"
+
+msgid "Renewed as it is used. <0/> has no effect over HTTPS."
+msgstr "使用期间会自动续期。<0/> 在 HTTPS 下无需设置。"
+
+msgid "Over plain HTTP, not renewed. <0/> makes it longer."
+msgstr "使用明文 HTTP,不会自动续期。设置 <0/> 可延长有效时间。"
+
+msgid "Over plain HTTP, set by <0/>. Renewed as it is used."
+msgstr "通过明文 HTTP 传输,由 <0/> 设置。使用时会自动续期。"
+
+msgid "{h, plural, one {# hour} other {# hours}}"
+msgstr "{h, plural, one {# 小时} other {# 小时}}"
+
+msgid "<0>{hiddenName}0> is hidden, so it isn't in this file. To export it, choose it under Export a location."
+msgstr "<0>{hiddenName}0> 处于隐藏状态,因此未包含在此文件中。如需导出,请在「导出空间」中单独选择它。"
+
+msgid "<0>{name}0> is hidden from your menu, Home, lists and search. This link still opens it."
+msgstr "<0>{name}0> 已从菜单、首页、列表和搜索中隐藏,但仍可通过此链接打开。"
+
+msgid "<0>{payer}0>'s personal key"
+msgstr "<0>{payer}0> 的个人密钥"
+
+msgid "<0>{personal}0> is showing because it's your only location. It hides again when you have another."
+msgstr "目前仅显示 <0>{personal}0>,因为它是你唯一的空间。当你拥有其他空间后,它会自动隐藏。"
+
+msgid "<0>{personal}0> is your only location, so it stays. Add or join another first."
+msgstr "<0>{personal}0> 是你唯一的空间,因此暂时保留。请先添加或加入另一个空间。"
+
+msgid "Hide <0>{personal}0>"
+msgstr "隐藏 <0>{personal}0>"
+
+msgid "It leaves the menu, Home, lists and search, for you only. Nothing in it changes, a link to it still opens it, and its reminders still reach you. Show it again here any time."
+msgstr "仅对你本人从菜单、首页、列表和搜索中隐藏。其中的内容不会改变,链接仍可正常打开,相关提醒也会继续送达。可随时在此恢复显示。"
+
+msgid "Show it again"
+msgstr "重新显示"
+
+msgid "This key pays for all of <0>{ownerName}0>'s homes: <1>{list}1>."
+msgstr "此密钥用于支付 <0>{ownerName}0> 名下的所有空间:<1>{list}1>。"
+
+msgid "Used for your private threads, questions that span owners, <0>{personal}0>, and a location you own and use alone that has no account key."
+msgstr "用于你的私密对话、跨所有者的提问、<0>{personal}0>,以及你独自拥有且未配置专属密钥的空间。"
+
+msgid "Your own key is for your private threads and questions that span owners."
+msgstr "你自己的密钥用于私人对话,以及跨所有者的提问。"
+
+msgid "Collapse places"
+msgstr "收起位置"
+
+msgid "Expand places"
+msgstr "展开位置"
+
+msgid "Resize places"
+msgstr "调整位置大小"
+
+msgid "{count, plural, one {# link keeps its Homebox title: Kept couldn't get one from Paperless.} other {# links keep their Homebox titles: Kept couldn't get them from Paperless.}}"
+msgstr "{count, plural, one {有 # 个链接保留了 Homebox 标题:Kept 无法从 Paperless 获取标题。} other {有 # 个链接保留了 Homebox 标题:Kept 无法从 Paperless 获取标题。}}"
+
+msgid "Passkeys work only at <0/>, because browsers tie a passkey to one address. Here, use your password or an email link."
+msgstr "通行密钥仅在 <0/> 上有效,因为浏览器会将通行密钥绑定到单个网址。在此处请使用密码或邮件登录链接。"
+
+msgid "The link opens at <0/> and signs you in there, not on this address. Can't reach it from here? Use your password."
+msgstr "该链接会在 <0/> 打开并完成登录,而不是在当前地址。无法访问该地址?请改用密码登录。"
+
+msgid "The link opens at <0/>. Set the new password there, then sign in here with it."
+msgstr "该链接将在 <0/> 打开。请在那里设置新密码,然后回到此处使用新密码登录。"
+
+msgid "Passkeys work only at <0/>, because browsers tie a passkey to one address. Add one there."
+msgstr "通行密钥仅在 <0/> 有效,因为浏览器会将通行密钥绑定到单一域名。请前往该地址添加。"
+
+msgid "To link one, go to <0/>: outside sign-ins come back to that address."
+msgstr "要关联账号,请前往 <0/>:外部登录都会回调到该地址。"
+
+msgid "Addresses"
+msgstr "地址"
+
+msgid "The main address. <0/> adds more."
+msgstr "主邮箱地址。点击 <0/> 可添加更多。"
+
+msgid "The main address, where links, mail and passkeys stay. Also, set by <0/>:"
+msgstr "主访问地址,用于分享链接、邮件与通行密钥。此外,当前由 <0/> 设置为:"
+
+msgid "{compartments, plural, one {Its # compartment goes to the trash with it, and comes back with it on Restore.} other {Its # compartments go to the trash with it, and come back with it on Restore.}}"
+msgstr "{compartments, plural, one {它的 # 个格位会随它一同移入回收站,还原时也会一并恢复。} other {它的 # 个格位会随它一同移入回收站,还原时也会一并恢复。}}"
+
+msgid "<0>{0}0> and its compartments hold {inside}. What should happen to them?"
+msgstr "<0>{0}0> 及其格位中存放了 {inside}。这些物品该如何处理?"
+
+msgid "Only {placeName} and its compartments go to the trash."
+msgstr "仅将 {placeName} 及其隔层移入回收站。"
+
+msgid "Rack"
+msgstr "机架"
+
+msgid "Rear"
+msgstr "背面"
+
+msgid "In the rack"
+msgstr "机架内"
+
+msgid "Full depth"
+msgstr "全进深"
+
+msgid "Rear, half depth"
+msgstr "后部,半深"
+
+msgid "Front, half depth"
+msgstr "前侧,半深"
+
+msgid "Beside the rails (0U)"
+msgstr "导轨旁(0U)"
+
+msgid "Not placed yet"
+msgstr "尚未放置"
+
+msgid "Place it"
+msgstr "放置"
+
+msgid "{units, plural, one {#U on a wall} other {#U on a wall}}"
+msgstr "{units, plural, one {壁挂 #U} other {壁挂 #U}}"
+
+msgid "{units, plural, one {10-inch rack, #U} other {10-inch rack, #U}}"
+msgstr "{units, plural, one {10 英寸机柜,#U} other {10 英寸机柜,#U}}"
+
+msgid "{units, plural, one {19-inch rack, #U} other {19-inch rack, #U}}"
+msgstr "{units, plural, one {19 英寸机架,#U} other {19 英寸机架,#U}}"
+
+msgctxt "rack"
+msgid "Units"
+msgstr "单位"
+
+msgid "How many rack units (U) high."
+msgstr "高度占多少个机架单位(U)。"
+
+msgid "Numbered from"
+msgstr "起始编号"
+
+msgid "The bottom"
+msgstr "底部"
+
+msgid "The top"
+msgstr "顶部"
+
+msgid "{units, plural, one {# unit, U1 at the top} other {# units, U1 at the top}}"
+msgstr "{units, plural, one {#U,U1 在顶部} other {#U,U1 在顶部}}"
+
+msgid "{units, plural, one {# unit, U1 at the bottom} other {# units, U1 at the bottom}}"
+msgstr "{units, plural, one {#U,U1 位于底部} other {#U,U1 位于底部}}"
+
+msgid "{u} is taken by {name} at the rear."
+msgstr "{u} 位背面已被 {name} 占用。"
+
+msgid "{u} is taken by {name} at the front."
+msgstr "{u} 正面位置已被 {name} 占用。"
+
+msgid "{units, plural, one {It doesn't fit: the rack is # unit high.} other {It doesn't fit: the rack is # units high.}}"
+msgstr "{units, plural, one {放不下:机柜高度仅 # U。} other {放不下:机柜高度仅 # U。}}"
+
+msgid "Gear with no height sits beside the rails."
+msgstr "无标准高度的设备安装在导轨旁。"
+
+msgid "Half units only: 1, 1.5, 2 …"
+msgstr "仅限半个单位:1、1.5、2……"
+
+msgid "Seen from"
+msgstr "观察面"
+
+msgid "Half depth"
+msgstr "半深"
+
+msgid "Placed {name}"
+msgstr "已放置 {name}"
+
+msgid "Took {name} off its unit"
+msgstr "已将 {name} 从其机位中移出"
+
+msgid "{name} in {rackName}"
+msgstr "{rackName} 中的 {name}"
+
+msgid "Starts at"
+msgstr "起始于"
+
+msgid "Its top unit, as the rack numbers them."
+msgstr "按机架编号顺序的顶部机位。"
+
+msgid "Its lowest unit, as the rack numbers them."
+msgstr "按机柜编号顺序的最低起始机位。"
+
+msgid "In rack units, halves allowed. 0 sits beside the rails."
+msgstr "以机架单位 (U) 计,支持半 U。0 表示位于导轨旁。"
+
+msgid "Faces"
+msgstr "朝向面"
+
+msgid "Take it off its unit"
+msgstr "从机柜 U 位取下"
+
+msgid "Rack units"
+msgstr "机架单元 (U)"
+
+msgid "This request has ended. Start again from Home Assistant."
+msgstr "此请求已失效,请从 Home Assistant 重新开始。"
+
+msgid "Declined. Home Assistant gets nothing."
+msgstr "已拒绝。Home Assistant 未获得任何访问权限。"
+
+msgid "Home Assistant asks to connect"
+msgstr "Home Assistant 请求连接"
+
+msgid "Code <0>{code}0>. Check that Home Assistant shows the same."
+msgstr "验证码 <0>{code}0>。请确认 Home Assistant 上显示的是同一组代码。"
+
+msgid "Decline"
+msgstr "拒绝"
+
+msgid "Connect Home Assistant"
+msgstr "连接 Home Assistant"
+
+msgid "Home Assistant reads Kept as you, in the locations you pick, and gets its token by itself: there is nothing to copy. Revoke it here any time."
+msgstr "Home Assistant 会以你的身份读取你选定空间的 Kept 数据,并自动获取令牌,无需手动复制。你可随时在此撤销授权。"
+
+msgid "Home Assistant is connected"
+msgstr "Home Assistant 已连接"
+
+msgid "Home Assistant finishes setting up on its own. The token is listed here as Home Assistant."
+msgstr "Home Assistant 会自动完成配置。该令牌将在此列表中显示为「Home Assistant」。"
+
+msgid "Came back damaged"
+msgstr "归还时已损坏"
+
+msgid "Came back damaged from {person}"
+msgstr "从 {person} 处归还时已损坏"
+
+msgid "Given back by"
+msgstr "归还人"
+
+msgid "given back by <0>{taker}0>"
+msgstr "由 <0>{taker}0> 归还"
+
+msgid "Not back yet"
+msgstr "尚未归还"
+
+msgid "since {from}"
+msgstr "自 {from} 起"
+
+msgid "Taken back by"
+msgstr "收回人"
+
+msgid "taken back by <0>{taker}0>"
+msgstr "已被 <0>{taker}0> 收回"
+
+msgid "Who had it"
+msgstr "曾借给谁"
+
+msgid "Position"
+msgstr "位置"
+
+msgid "With Suggest where I am on, Capture picks this location when you're here. Your phone's position is compared on the phone and never sent. Only owners and admins see this."
+msgstr "开启“智能推荐当前空间”后,当你身处此地时,“采集”会自动选中此空间。手机位置仅在本地比对,绝不会上传。仅所有者和管理员可见此设置。"
+
+msgid "Latitude"
+msgstr "纬度"
+
+msgid "Longitude"
+msgstr "经度"
+
+msgid "Enter a number from {from} to {to}."
+msgstr "请输入 {from} 到 {to} 之间的数字。"
+
+msgid "Use where I am now"
+msgstr "使用我当前所在位置"
+
+msgid "Couldn't read where you are. Try again, or type it."
+msgstr "无法获取当前位置。请重试,或手动输入。"
+
+msgid "Open in maps"
+msgstr "在地图中打开"
+
+msgid "Remove position"
+msgstr "移除位置坐标"
+
+msgid "Position removed"
+msgstr "位置已移除"
+
+msgid "{w} × {d}"
+msgstr "{w} × {d}"
+
+msgid "On the wall, {hangs} up"
+msgstr "挂在墙上,{hangs} 处"
+
+msgid "Enter feet and inches, like {example}."
+msgstr "输入英尺和英寸,例如 {example}。"
+
+msgid "<0>{room}0>, from the plan, not added, {w} by {d}"
+msgstr "<0>{room}0>,来自平面图,尚未添加,{w} × {d}"
+
+msgid "Enter inches, like {example}."
+msgstr "请输入英寸数,例如 {example}。"
+
+msgid "Scale from the doors, taken as {door} wide: check one room"
+msgstr "按门宽推算比例(默认门宽 {door}):请核对一个房间"
+
+msgid "Under {smallest}: too small for the map."
+msgstr "小于 {smallest}:尺寸过小,无法在平面图上显示。"
+
+msgid "Couldn't change the units"
+msgstr "无法更改单位"
+
+msgid "Units"
+msgstr "单位"
+
+msgid "Sizes on the map, label sizes, fuel use and a new vehicle’s odometer. What you’ve saved stays as it is."
+msgstr "用于地图尺寸、标签尺寸、油耗单位以及新车辆的里程表单位。已保存的记录保持不变。"
+
+msgid "Metric"
+msgstr "公制"
+
+msgid "Imperial"
+msgstr "英制"
+
+msgid "Change unit"
+msgstr "更改单位"
+
+msgid "Unit changed to {toLabel}"
+msgstr "单位已更改为 {toLabel}"
+
+msgid "{n, plural, one {# reading converted} other {# readings converted}}"
+msgstr "{n, plural, one {已转换 # 条读数} other {已转换 # 条读数}}"
+
+msgid "Couldn't change the unit"
+msgstr "无法更改单位"
+
+msgid "From {fromLabel} to {toLabel}"
+msgstr "从 {fromLabel} 到 {toLabel}"
+
+msgid "What to change"
+msgstr "要更改的内容"
+
+msgid "Convert the readings"
+msgstr "转换读数"
+
+msgid "Every reading, the replacement offset, the daily limit and the schedules on this odometer change to {toLabel}."
+msgstr "此里程表上的每条读数、更换偏移量、每日上限和计划都将切换为 {toLabel}。"
+
+msgid "Relabel only"
+msgstr "仅重新贴标"
+
+msgid "The readings were always in {toLabel}. Every value stays as it is."
+msgstr "读数原本就是以 {toLabel} 为单位记录的,所有数值将保持原样。"
+
+msgid "New unit"
+msgstr "新单位"
+
+msgid "Only the unit's name changes. The readings stay as they are."
+msgstr "仅更改单位名称,已有读数保持不变。"
+
+msgid "Latest reading: {0} {fromLabel} becomes {1} {toLabel}"
+msgstr "最新读数:{0} {fromLabel} 将转换为 {1} {toLabel}"
+
+msgid "{0, plural, one {# reading changes} other {# readings change}}"
+msgstr "{0, plural, one {# 条读数将变更} other {# 条读数将变更}}"
+
+msgid "Replacement offset: {0} becomes {1}"
+msgstr "替换偏移量:{0} 变为 {1}"
+
+msgid "Daily limit: {0} becomes {1}"
+msgstr "每日上限:由 {0} 调整为 {1}"
+
+msgid "{0, plural, one {# schedule on it changes} other {# schedules on it change}}"
+msgstr "{0, plural, one {其上的 # 个计划将随之更改} other {其上的 # 个计划将随之更改}}"
+
+msgid "It goes in the history, and you can undo it."
+msgstr "操作会记入历史记录,且你可以随时撤销。"
+
+msgid "A room is at least {min} across."
+msgstr "房间宽度至少为 {min}。"
+
+msgid "A room is at most {max} across."
+msgstr "房间宽度上限为 {max}。"
+
+msgid "{a} × {b} in"
+msgstr "{a} × {b} 英寸"
+
+msgid "{width} in tape"
+msgstr "{width} 英寸色带"
+
+msgid "The photo shows {seenUnit}, and this odometer counts {unit}. {0} {seenUnit} is {1} {unit}."
+msgstr "照片显示单位为 {seenUnit},而此里程表使用 {unit}。换算关系:{0} {seenUnit} = {1} {unit}。"
+
+msgid "Use {0} {unit}"
+msgstr "消耗 {0} {unit}"
+
+msgid "Readings converted"
+msgstr "已转换读数"
+
+msgid "Meter unit changed"
+msgstr "表计单位已更改"
+
+msgid "Water purifier"
+msgstr "净水器"
+
+msgctxt "how many shelves"
+msgid "Shelves"
+msgstr "层数"
+
+msgid "Counts are off"
+msgstr "盘点功能未开启"
+
+msgid "An owner or admin turns them on in a location's What to track."
+msgstr "所有者或管理员可在空间设置的「追踪内容」中开启此功能。"
+
+msgid "Counts are off here: this lists the box checks."
+msgstr "此处未开启盘点功能:下方仅列出箱内核对记录。"
diff --git a/apps/web/src/test/screens/display.test.tsx b/apps/web/src/test/screens/display.test.tsx
index 42d843e2..48cf33af 100644
--- a/apps/web/src/test/screens/display.test.tsx
+++ b/apps/web/src/test/screens/display.test.tsx
@@ -39,6 +39,7 @@ describe('Settings → Me → Display', () => {
'Italiano',
'Українська',
'Tiếng Việt',
+ '简体中文',
]);
// A flag (SVG, never an emoji) beside every name, marked decorative.
for (const o of options) {
diff --git a/docker/notices.sh b/docker/notices.sh
index 3c95019b..a27c0690 100644
--- a/docker/notices.sh
+++ b/docker/notices.sh
@@ -18,6 +18,7 @@ node /notices/bin/third-party-notices.mjs \
--restic-version "$(restic version | cut -d' ' -f2)" \
--extra "IBM Plex Sans (the inventory report's font)|OFL-1.1|/notices/fonts/IBMPlexSans-OFL.txt" \
--extra "IBM Plex Sans Arabic (the inventory report's font)|OFL-1.1|/notices/fonts/IBMPlexSansArabic-OFL.txt" \
+ --extra "IBM Plex Sans SC (the inventory report's font)|OFL-1.1|/notices/fonts/IBMPlexSansSC-OFL.txt" \
--extra "IBM Plex Mono (the inventory report's font)|OFL-1.1|/notices/fonts/IBMPlexMono-OFL.txt" \
--extra "Poly Haven models (the location map's furniture, plants and AC units)|CC0-1.0|/notices/map-models-NOTICE.txt" \
--version "$1" --arch "$2" \
diff --git a/homeassistant/kept/translations/zh-Hans.yaml b/homeassistant/kept/translations/zh-Hans.yaml
new file mode 100644
index 00000000..e7648b4d
--- /dev/null
+++ b/homeassistant/kept/translations/zh-Hans.yaml
@@ -0,0 +1,100 @@
+configuration:
+ public_url:
+ name: Kept 访问地址
+ description: >-
+ 手机、打印标签和邮件链接使用的地址,例如
+ http://homeassistant.local:8080 或 https://kept.example.org 。留空则使用
+ Home Assistant 的主机名与此应用的端口。请勿包含路径。
+ log_level:
+ name: 日志详细程度
+ description: Kept 写入「日志」标签页的信息量。
+ smtp_url:
+ name: 发件服务器
+ description: >-
+ 包含账号信息的 smtp:// 或 smtps:// 地址,例如
+ smtps://user:password@mail.example.org 。留空则不发送邮件。
+ smtp_from:
+ name: 发件人地址
+ description: Kept 邮件的发件人栏,例如 Kept 。
+ ssl:
+ name: 在 Kept 端口启用 https
+ description: >-
+ 使用 /ssl 目录中 Home Assistant 的证书在 Kept 端口上提供 https 服务。令牌、通行密钥、相机与可安装应用均需要
+ https。证书续期后请重启此应用。
+ certfile:
+ name: 证书文件
+ description: /ssl 目录中的证书文件名。
+ keyfile:
+ name: 私钥文件
+ description: /ssl 目录中的私钥文件名。
+ hsts:
+ name: HSTS
+ description: >-
+ 启用 https 时,Kept 会告知浏览器在一年内对此主机名的所有端口(包括 Home Assistant 自身)均使用
+ https。若此主机名上的 Home Assistant 或其他应用仍使用明文 http,请设为 off;浏览器下次通过 https 访问 Kept 时会清除该策略。
+ http_sign_in_days:
+ name: 明文 http 登录有效期
+ description: >-
+ 在明文 http 下保持登录的天数(1 至 30 天,随使用自动续期;家庭局域网建议设为 7)。留空则为 12 小时且不自动续期。启用
+ https 时此项无效。在明文 http 下,同一网络中能截获流量的人可能复制登录凭据;开启此项后,被复制的凭据在使用期间将持续有效,直至该设备退出登录或你在其他设备上注销会话。
+ extra_addresses:
+ name: 额外访问地址
+ description: >-
+ 此 Kept 实例响应的其他地址,以英文逗号分隔,格式须与浏览器地址栏完全一致,例如
+ http://192.0.2.20:8080 。不支持通配符,且 http 或 https 协议须与 Kept 主地址一致。每个地址独立登录;分享链接、邮件、通行密钥与应用连接仍使用
+ Kept 主地址。请仅填写确实指向此 Kept 实例的地址。
+ oidc_issuer:
+ name: OIDC 签发方 (Issuer)
+ description: >-
+ 使用自建身份提供商登录:请按其发现文档原样填写签发方地址。同时设置客户端 ID 后即可启用 OIDC 登录。需注册的回调地址为 Kept 访问地址后接
+ /api/v1/auth/callback/oidc 。
+ oidc_client_id:
+ name: OIDC 客户端 ID
+ description: 身份提供商分配的客户端 ID。
+ oidc_client_secret:
+ name: OIDC 客户端密钥
+ description: 机密客户端的客户端密钥;公开客户端请留空。
+ oidc_name:
+ name: OIDC 按钮名称
+ description: >-
+ 登录按钮「使用 … 登录」中显示的提供商名称,最多 60 个字符。留空则显示 OIDC。
+ oidc_autoprovision_domains:
+ name: 按邮箱域名自动注册 OIDC 账号
+ description: >-
+ 首次登录时自动创建账号的邮箱域名列表,以英文逗号分隔(精确匹配,不含子域名)。留空则仅限受邀用户。
+ oidc_autoprovision_groups:
+ name: 按用户组自动注册 OIDC 账号
+ description: >-
+ 首次登录时自动创建账号的用户组列表,以英文逗号分隔(精确匹配)。留空则仅限受邀用户。
+ oidc_groups_claim:
+ name: OIDC 用户组声明字段
+ description: >-
+ ID 令牌中存放用户组的声明字段名。留空则为 groups。
+ oidc_scopes:
+ name: OIDC 权限范围 (Scopes)
+ description: >-
+ 请求的权限范围,以空格分隔。留空则为 openid email profile。
+ google_client_id:
+ name: Google 客户端 ID
+ description: >-
+ 使用 Google Cloud 的 OAuth 客户端启用 Google 登录。同时设置密钥后即可启用,仅对已有账号与受邀用户开放。Google 要求
+ Kept 访问地址为公网域名的 https 地址(不支持 http、.local 或 IP 地址):请设置 Kept 访问地址(例如在 Kept 端口启用 https 的 DuckDNS 域名)。需注册的回调地址为 Kept 访问地址后接
+ /api/v1/auth/callback/google 。
+ google_client_secret:
+ name: Google 客户端密钥
+ description: OAuth 客户端的密钥。
+ apprise_url:
+ name: Apprise 服务器
+ description: >-
+ 发送 Apprise 通知渠道所使用的 Apprise API 服务器地址,例如
+ http://apprise:8000 。留空则无法添加 Apprise 通知渠道。
+ signup_open:
+ name: 开放注册
+ description: >-
+ 设为 true 将锁定为开放注册,设为 false 将锁定为关闭注册(仅限邀请);此时管理后台中的对应设置会显示为已锁定。留空则由管理员在 Kept 内决定(管理 → 注册设置)。
+ max_file_mb:
+ name: 上传大小上限 (MB)
+ description: >-
+ 单次上传允许的最大文件体积,1 至 2048。留空则为 25。
+network:
+ 8080/tcp: Kept 自身服务端口,供手机、打印标签与邮件链接访问
diff --git a/homeassistant/kept/translations/zh.yaml b/homeassistant/kept/translations/zh.yaml
new file mode 100644
index 00000000..e7648b4d
--- /dev/null
+++ b/homeassistant/kept/translations/zh.yaml
@@ -0,0 +1,100 @@
+configuration:
+ public_url:
+ name: Kept 访问地址
+ description: >-
+ 手机、打印标签和邮件链接使用的地址,例如
+ http://homeassistant.local:8080 或 https://kept.example.org 。留空则使用
+ Home Assistant 的主机名与此应用的端口。请勿包含路径。
+ log_level:
+ name: 日志详细程度
+ description: Kept 写入「日志」标签页的信息量。
+ smtp_url:
+ name: 发件服务器
+ description: >-
+ 包含账号信息的 smtp:// 或 smtps:// 地址,例如
+ smtps://user:password@mail.example.org 。留空则不发送邮件。
+ smtp_from:
+ name: 发件人地址
+ description: Kept 邮件的发件人栏,例如 Kept 。
+ ssl:
+ name: 在 Kept 端口启用 https
+ description: >-
+ 使用 /ssl 目录中 Home Assistant 的证书在 Kept 端口上提供 https 服务。令牌、通行密钥、相机与可安装应用均需要
+ https。证书续期后请重启此应用。
+ certfile:
+ name: 证书文件
+ description: /ssl 目录中的证书文件名。
+ keyfile:
+ name: 私钥文件
+ description: /ssl 目录中的私钥文件名。
+ hsts:
+ name: HSTS
+ description: >-
+ 启用 https 时,Kept 会告知浏览器在一年内对此主机名的所有端口(包括 Home Assistant 自身)均使用
+ https。若此主机名上的 Home Assistant 或其他应用仍使用明文 http,请设为 off;浏览器下次通过 https 访问 Kept 时会清除该策略。
+ http_sign_in_days:
+ name: 明文 http 登录有效期
+ description: >-
+ 在明文 http 下保持登录的天数(1 至 30 天,随使用自动续期;家庭局域网建议设为 7)。留空则为 12 小时且不自动续期。启用
+ https 时此项无效。在明文 http 下,同一网络中能截获流量的人可能复制登录凭据;开启此项后,被复制的凭据在使用期间将持续有效,直至该设备退出登录或你在其他设备上注销会话。
+ extra_addresses:
+ name: 额外访问地址
+ description: >-
+ 此 Kept 实例响应的其他地址,以英文逗号分隔,格式须与浏览器地址栏完全一致,例如
+ http://192.0.2.20:8080 。不支持通配符,且 http 或 https 协议须与 Kept 主地址一致。每个地址独立登录;分享链接、邮件、通行密钥与应用连接仍使用
+ Kept 主地址。请仅填写确实指向此 Kept 实例的地址。
+ oidc_issuer:
+ name: OIDC 签发方 (Issuer)
+ description: >-
+ 使用自建身份提供商登录:请按其发现文档原样填写签发方地址。同时设置客户端 ID 后即可启用 OIDC 登录。需注册的回调地址为 Kept 访问地址后接
+ /api/v1/auth/callback/oidc 。
+ oidc_client_id:
+ name: OIDC 客户端 ID
+ description: 身份提供商分配的客户端 ID。
+ oidc_client_secret:
+ name: OIDC 客户端密钥
+ description: 机密客户端的客户端密钥;公开客户端请留空。
+ oidc_name:
+ name: OIDC 按钮名称
+ description: >-
+ 登录按钮「使用 … 登录」中显示的提供商名称,最多 60 个字符。留空则显示 OIDC。
+ oidc_autoprovision_domains:
+ name: 按邮箱域名自动注册 OIDC 账号
+ description: >-
+ 首次登录时自动创建账号的邮箱域名列表,以英文逗号分隔(精确匹配,不含子域名)。留空则仅限受邀用户。
+ oidc_autoprovision_groups:
+ name: 按用户组自动注册 OIDC 账号
+ description: >-
+ 首次登录时自动创建账号的用户组列表,以英文逗号分隔(精确匹配)。留空则仅限受邀用户。
+ oidc_groups_claim:
+ name: OIDC 用户组声明字段
+ description: >-
+ ID 令牌中存放用户组的声明字段名。留空则为 groups。
+ oidc_scopes:
+ name: OIDC 权限范围 (Scopes)
+ description: >-
+ 请求的权限范围,以空格分隔。留空则为 openid email profile。
+ google_client_id:
+ name: Google 客户端 ID
+ description: >-
+ 使用 Google Cloud 的 OAuth 客户端启用 Google 登录。同时设置密钥后即可启用,仅对已有账号与受邀用户开放。Google 要求
+ Kept 访问地址为公网域名的 https 地址(不支持 http、.local 或 IP 地址):请设置 Kept 访问地址(例如在 Kept 端口启用 https 的 DuckDNS 域名)。需注册的回调地址为 Kept 访问地址后接
+ /api/v1/auth/callback/google 。
+ google_client_secret:
+ name: Google 客户端密钥
+ description: OAuth 客户端的密钥。
+ apprise_url:
+ name: Apprise 服务器
+ description: >-
+ 发送 Apprise 通知渠道所使用的 Apprise API 服务器地址,例如
+ http://apprise:8000 。留空则无法添加 Apprise 通知渠道。
+ signup_open:
+ name: 开放注册
+ description: >-
+ 设为 true 将锁定为开放注册,设为 false 将锁定为关闭注册(仅限邀请);此时管理后台中的对应设置会显示为已锁定。留空则由管理员在 Kept 内决定(管理 → 注册设置)。
+ max_file_mb:
+ name: 上传大小上限 (MB)
+ description: >-
+ 单次上传允许的最大文件体积,1 至 2048。留空则为 25。
+network:
+ 8080/tcp: Kept 自身服务端口,供手机、打印标签与邮件链接访问
diff --git a/packages/shared/src/builtin-names.test.ts b/packages/shared/src/builtin-names.test.ts
index 0eb569ee..8bff0b39 100644
--- a/packages/shared/src/builtin-names.test.ts
+++ b/packages/shared/src/builtin-names.test.ts
@@ -7,10 +7,10 @@ import {
} from './builtin-names.js';
import { BUILTIN_TYPES } from './builtin-types.js';
-const MORE = ['de', 'es', 'fr', 'it', 'uk', 'vi'] as const;
+const MORE = ['de', 'es', 'fr', 'it', 'uk', 'vi', 'zh'] as const;
describe('built-in names in every language that has them', () => {
- it('names every built-in type and field in French, German, Italian, Spanish, Ukrainian and Vietnamese', () => {
+ it('names every built-in type and field in French, German, Italian, Simplified Chinese, Spanish, Ukrainian and Vietnamese', () => {
const typeKeys = BUILTIN_TYPES.map((t) => t.key).sort();
const fieldKeys = [...new Set(BUILTIN_TYPES.flatMap((t) => t.fields.map((f) => f.key)))].sort();
expect(Object.keys(BUILTIN_TYPE_NAMES_MORE).sort()).toEqual(typeKeys);
@@ -35,6 +35,8 @@ describe('built-in names in every language that has them', () => {
expect(builtinTypeName('furniture', 'es')).toBe('Muebles');
expect(builtinTypeName('furniture', 'vi')).toBe('Nội thất');
expect(builtinFieldName('voltage', 'vi')).toBe('Điện áp');
+ expect(builtinTypeName('furniture', 'zh')).toBe('家具');
+ expect(builtinFieldName('voltage', 'zh')).toBe('电压');
expect(builtinTypeName('no_such_type', 'it')).toBeUndefined();
expect(builtinFieldName('no_such_field', 'en')).toBeUndefined();
});
diff --git a/packages/shared/src/builtin-names.ts b/packages/shared/src/builtin-names.ts
index 8054be19..c69b5d0d 100644
--- a/packages/shared/src/builtin-names.ts
+++ b/packages/shared/src/builtin-names.ts
@@ -4,7 +4,7 @@
*/
import { BUILTIN_TYPES, builtinType } from './builtin-types.js';
-export type BuiltinNameLocale = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi';
+export type BuiltinNameLocale = 'ar' | 'de' | 'en' | 'es' | 'fr' | 'it' | 'uk' | 'vi' | 'zh';
type More = {
readonly de: string;
readonly es: string;
@@ -12,6 +12,7 @@ type More = {
readonly it: string;
readonly uk: string;
readonly vi: string;
+ readonly zh: string;
};
export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
@@ -22,6 +23,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Dispositivo',
uk: 'Пристрій',
vi: 'Thiết bị',
+ zh: '设备',
},
furniture: {
de: 'Möbel',
@@ -30,6 +32,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Mobili',
uk: 'Меблі',
vi: 'Nội thất',
+ zh: '家具',
},
appliance: {
de: 'Haushaltsgerät',
@@ -38,6 +41,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Elettrodomestico',
uk: 'Побутова техніка',
vi: 'Đồ gia dụng',
+ zh: '家电',
},
large_appliance: {
de: 'Großgerät',
@@ -46,6 +50,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Grande elettrodomestico',
uk: 'Велика побутова техніка',
vi: 'Đồ gia dụng lớn',
+ zh: '大家电',
},
small_appliance: {
de: 'Kleingerät',
@@ -54,6 +59,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Piccolo elettrodomestico',
uk: 'Дрібна побутова техніка',
vi: 'Đồ gia dụng nhỏ',
+ zh: '小家电',
},
electronics: {
de: 'Elektronik',
@@ -62,6 +68,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Elettronica',
uk: 'Електроніка',
vi: 'Đồ điện tử',
+ zh: '电子产品',
},
phone: {
de: 'Telefon',
@@ -70,6 +77,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Telefono',
uk: 'Телефон',
vi: 'Điện thoại',
+ zh: '手机',
},
tablet: {
de: 'Tablet',
@@ -78,6 +86,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Tablet',
uk: 'Планшет',
vi: 'Máy tính bảng',
+ zh: '平板电脑',
},
computer: {
de: 'Computer',
@@ -86,6 +95,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Computer',
uk: 'Комп’ютер',
vi: 'Máy tính',
+ zh: '电脑',
},
tv_display: {
de: 'TV / Bildschirm',
@@ -94,6 +104,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'TV / schermo',
uk: 'Телевізор / екран',
vi: 'TV / màn hình',
+ zh: '电视 / 显示器',
},
network_device: {
de: 'Netzwerkgerät',
@@ -102,6 +113,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Dispositivo di rete',
uk: 'Мережевий пристрій',
vi: 'Thiết bị mạng',
+ zh: '网络设备',
},
camera: {
de: 'Kamera',
@@ -110,6 +122,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Fotocamera',
uk: 'Камера',
vi: 'Máy ảnh',
+ zh: '相机',
},
console: {
de: 'Spielkonsole',
@@ -118,8 +131,17 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Console',
uk: 'Ігрова консоль',
vi: 'Máy chơi game',
+ zh: '游戏主机',
+ },
+ cable: {
+ de: 'Kabel',
+ es: 'Cable',
+ fr: 'Câble',
+ it: 'Cavo',
+ uk: 'Кабель',
+ vi: 'Cáp',
+ zh: '线缆',
},
- cable: { de: 'Kabel', es: 'Cable', fr: 'Câble', it: 'Cavo', uk: 'Кабель', vi: 'Cáp' },
charger: {
de: 'Ladegerät / Netzteil',
es: 'Cargador / fuente de alimentación',
@@ -127,6 +149,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Caricatore / alimentatore',
uk: 'Зарядний пристрій / блок живлення',
vi: 'Bộ sạc / nguồn',
+ zh: '充电器 / 电源',
},
tool: {
de: 'Werkzeug',
@@ -135,6 +158,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Attrezzo',
uk: 'Інструмент',
vi: 'Dụng cụ',
+ zh: '工具',
},
power_tool: {
de: 'Elektrowerkzeug',
@@ -143,6 +167,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Elettroutensile',
uk: 'Електроінструмент',
vi: 'Dụng cụ điện',
+ zh: '电动工具',
},
box_bin: {
de: 'Kiste / Box',
@@ -151,6 +176,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Scatola / contenitore',
uk: 'Коробка / контейнер',
vi: 'Hộp / thùng',
+ zh: '收纳箱 / 储物箱',
},
safe: {
de: 'Tresor',
@@ -159,6 +185,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Cassaforte',
uk: 'Сейф',
vi: 'Két sắt',
+ zh: '保险柜',
},
vehicle: {
de: 'Fahrzeug',
@@ -167,9 +194,26 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Veicolo',
uk: 'Транспортний засіб',
vi: 'Xe',
+ zh: '车辆 / 载具',
+ },
+ car: {
+ de: 'Auto',
+ es: 'Coche',
+ fr: 'Voiture',
+ it: 'Auto',
+ uk: 'Автомобіль',
+ vi: 'Ô tô',
+ zh: '汽车',
+ },
+ motorbike: {
+ de: 'Motorrad',
+ es: 'Moto',
+ fr: 'Moto',
+ it: 'Moto',
+ uk: 'Мотоцикл',
+ vi: 'Xe máy',
+ zh: '摩托车',
},
- car: { de: 'Auto', es: 'Coche', fr: 'Voiture', it: 'Auto', uk: 'Автомобіль', vi: 'Ô tô' },
- motorbike: { de: 'Motorrad', es: 'Moto', fr: 'Moto', it: 'Moto', uk: 'Мотоцикл', vi: 'Xe máy' },
bicycle: {
de: 'Fahrrad',
es: 'Bicicleta',
@@ -177,6 +221,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Bicicletta',
uk: 'Велосипед',
vi: 'Xe đạp',
+ zh: '自行车',
},
generator: {
de: 'Stromerzeuger',
@@ -185,6 +230,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Generatore',
uk: 'Генератор',
vi: 'Máy phát điện',
+ zh: '发电机',
},
safety_equipment: {
de: 'Sicherheitsausrüstung',
@@ -193,6 +239,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Dispositivi di sicurezza',
uk: 'Засоби безпеки',
vi: 'Thiết bị an toàn',
+ zh: '安全设备',
},
fire_extinguisher: {
de: 'Feuerlöscher',
@@ -201,6 +248,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Estintore',
uk: 'Вогнегасник',
vi: 'Bình chữa cháy',
+ zh: '灭火器',
},
first_aid_kit: {
de: 'Erste-Hilfe-Set',
@@ -209,6 +257,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Kit di pronto soccorso',
uk: 'Аптечка першої допомоги',
vi: 'Hộp sơ cứu',
+ zh: '急救箱',
},
smoke_detector: {
de: 'Rauchmelder',
@@ -217,6 +266,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Rilevatore di fumo',
uk: 'Детектор диму',
vi: 'Cảm biến khói',
+ zh: '烟雾报警器',
},
child_car_seat: {
de: 'Kindersitz',
@@ -225,6 +275,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Seggiolino auto',
uk: 'Дитяче автокрісло',
vi: 'Ghế ô tô trẻ em',
+ zh: '儿童安全座椅',
},
valuables: {
de: 'Wertsachen',
@@ -233,6 +284,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Oggetti di valore',
uk: 'Цінні речі',
vi: 'Đồ giá trị',
+ zh: '贵重物品',
},
collectible: {
de: 'Sammlerstück',
@@ -241,6 +293,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Oggetto da collezione',
uk: 'Колекційний предмет',
vi: 'Đồ sưu tầm',
+ zh: '收藏品',
},
consumables: {
de: 'Verbrauchsmaterial',
@@ -249,6 +302,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Materiali di consumo',
uk: 'Витратні матеріали',
vi: 'Vật tư tiêu hao',
+ zh: '耗材',
},
batteries: {
de: 'Batterien',
@@ -257,6 +311,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Batterie',
uk: 'Батарейки',
vi: 'Pin',
+ zh: '电池',
},
filters: {
de: 'Filter',
@@ -265,6 +320,7 @@ export const BUILTIN_TYPE_NAMES_MORE: Readonly> = {
it: 'Filtri',
uk: 'Фільтри',
vi: 'Bộ lọc',
+ zh: '滤芯 / 滤网',
},
};
@@ -276,6 +332,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Sistema operativo',
uk: 'Операційна система',
vi: 'Hệ điều hành',
+ zh: '操作系统',
},
os_version: {
de: 'Systemversion',
@@ -284,6 +341,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Versione del sistema',
uk: 'Версія системи',
vi: 'Phiên bản hệ điều hành',
+ zh: '系统版本',
},
firmware: {
de: 'Firmware',
@@ -292,6 +350,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Firmware',
uk: 'Мікропрограма',
vi: 'Firmware',
+ zh: '固件',
},
mac_address: {
de: 'MAC-Adresse',
@@ -300,6 +359,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Indirizzo MAC',
uk: 'MAC-адреса',
vi: 'Địa chỉ MAC',
+ zh: 'MAC 地址',
},
linked_account: {
de: 'Verknüpftes Konto oder Login',
@@ -308,6 +368,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Account collegato o login',
uk: 'Пов’язаний обліковий запис або логін',
vi: 'Tài khoản liên kết hoặc đăng nhập',
+ zh: '关联账号或登录信息',
},
material: {
de: 'Material',
@@ -316,6 +377,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Materiale',
uk: 'Матеріал',
vi: 'Chất liệu',
+ zh: '材质',
},
dimensions: {
de: 'Abmessungen',
@@ -324,8 +386,9 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Dimensioni',
uk: 'Розміри',
vi: 'Kích thước',
+ zh: '尺寸',
},
- imei: { de: 'IMEI', es: 'IMEI', fr: 'IMEI', it: 'IMEI', uk: 'IMEI', vi: 'IMEI' },
+ imei: { de: 'IMEI', es: 'IMEI', fr: 'IMEI', it: 'IMEI', uk: 'IMEI', vi: 'IMEI', zh: 'IMEI' },
imei_2: {
de: 'Zweite IMEI',
es: 'Segundo IMEI',
@@ -333,6 +396,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Secondo IMEI',
uk: 'Другий IMEI',
vi: 'IMEI thứ hai',
+ zh: '第二 IMEI',
},
storage: {
de: 'Speicher',
@@ -341,9 +405,10 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Memoria',
uk: 'Пам’ять',
vi: 'Bộ nhớ',
+ zh: '存储容量',
},
- cpu: { de: 'CPU', es: 'CPU', fr: 'CPU', it: 'CPU', uk: 'CPU', vi: 'CPU' },
- ram: { de: 'RAM', es: 'RAM', fr: 'RAM', it: 'RAM', uk: 'RAM', vi: 'RAM' },
+ cpu: { de: 'CPU', es: 'CPU', fr: 'CPU', it: 'CPU', uk: 'CPU', vi: 'CPU', zh: 'CPU' },
+ ram: { de: 'RAM', es: 'RAM', fr: 'RAM', it: 'RAM', uk: 'RAM', vi: 'RAM', zh: '内存' },
licence_key: {
de: 'Lizenzschlüssel',
es: 'Clave de licencia',
@@ -351,6 +416,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Chiave di licenza',
uk: 'Ліцензійний ключ',
vi: 'Khóa giấy phép',
+ zh: '许可证密钥',
},
screen_size: {
de: 'Bildschirmgröße',
@@ -359,6 +425,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Dimensioni schermo',
uk: 'Розмір екрана',
vi: 'Kích thước màn hình',
+ zh: '屏幕尺寸',
},
wifi_password: {
de: 'Wi-Fi-Passwort',
@@ -367,6 +434,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Password Wi-Fi',
uk: 'Пароль Wi-Fi',
vi: 'Mật khẩu Wi-Fi',
+ zh: 'Wi-Fi 密码',
},
connector_a: {
de: 'Stecker A',
@@ -375,6 +443,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Connettore A',
uk: 'Роз’єм A',
vi: 'Cổng kết nối A',
+ zh: '接口 A',
},
connector_b: {
de: 'Stecker B',
@@ -383,6 +452,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Connettore B',
uk: 'Роз’єм B',
vi: 'Cổng kết nối B',
+ zh: '接口 B',
},
length: {
de: 'Länge',
@@ -391,6 +461,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Lunghezza',
uk: 'Довжина',
vi: 'Độ dài',
+ zh: '长度',
},
wattage: {
de: 'Leistung',
@@ -399,6 +470,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Potenza',
uk: 'Потужність',
vi: 'Công suất',
+ zh: '功率',
},
connector: {
de: 'Stecker',
@@ -407,6 +479,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Connettore',
uk: 'Роз’єм',
vi: 'Cổng kết nối',
+ zh: '接口',
},
voltage: {
de: 'Spannung',
@@ -415,6 +488,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Tensione',
uk: 'Напруга',
vi: 'Điện áp',
+ zh: '电压',
},
battery_platform: {
de: 'Akkusystem',
@@ -423,6 +497,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Piattaforma batteria',
uk: 'Тип акумулятора',
vi: 'Nền tảng pin',
+ zh: '电池平台',
},
combination: {
de: 'Kombination',
@@ -431,8 +506,17 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Combinazione',
uk: 'Комбінація',
vi: 'Mã tổ hợp',
+ zh: '密码组合',
+ },
+ vin: {
+ de: 'VIN',
+ es: 'VIN',
+ fr: 'VIN',
+ it: 'VIN',
+ uk: 'VIN',
+ vi: 'VIN',
+ zh: '车架号 (VIN)',
},
- vin: { de: 'VIN', es: 'VIN', fr: 'VIN', it: 'VIN', uk: 'VIN', vi: 'VIN' },
plate: {
de: 'Kennzeichen',
es: 'Matrícula',
@@ -440,6 +524,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Targa',
uk: 'Номерний знак',
vi: 'Biển số',
+ zh: '车牌号',
},
frame_number: {
de: 'Rahmennummer',
@@ -448,6 +533,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Numero di telaio',
uk: 'Номер рами',
vi: 'Số khung',
+ zh: '车架编号',
},
appraisal_value: {
de: 'Schätzwert',
@@ -456,6 +542,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Valore di stima',
uk: 'Оціночна вартість',
vi: 'Giá trị thẩm định',
+ zh: '评估价值',
},
appraisal_date: {
de: 'Datum der Schätzung',
@@ -464,6 +551,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Data della stima',
uk: 'Дата оцінки',
vi: 'Ngày thẩm định',
+ zh: '评估日期',
},
edition: {
de: 'Ausgabe',
@@ -472,6 +560,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Edizione',
uk: 'Видання',
vi: 'Phiên bản',
+ zh: '版本',
},
condition_grade: {
de: 'Erhaltungsgrad',
@@ -480,6 +569,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Stato di conservazione',
uk: 'Стан збереження',
vi: 'Xếp hạng tình trạng',
+ zh: '品相等级',
},
provenance_notes: {
de: 'Notizen zur Herkunft',
@@ -488,8 +578,17 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Note sulla provenienza',
uk: 'Примітки про походження',
vi: 'Ghi chú xuất xứ',
+ zh: '来源说明',
+ },
+ size: {
+ de: 'Größe',
+ es: 'Formato',
+ fr: 'Format',
+ it: 'Formato',
+ uk: 'Формат',
+ vi: 'Kích thước',
+ zh: '型号规格',
},
- size: { de: 'Größe', es: 'Formato', fr: 'Format', it: 'Formato', uk: 'Формат', vi: 'Kích thước' },
chemistry: {
de: 'Zellchemie',
es: 'Química',
@@ -497,6 +596,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Chimica',
uk: 'Тип елемента',
vi: 'Thành phần hóa học',
+ zh: '电池类型',
},
fits: {
de: 'Passend für',
@@ -505,6 +605,7 @@ export const BUILTIN_FIELD_NAMES_MORE: Readonly> = {
it: 'Compatibile con',
uk: 'Сумісний із',
vi: 'Tương thích với',
+ zh: '适用设备',
},
};
diff --git a/packages/shared/src/homebox.test.ts b/packages/shared/src/homebox.test.ts
index e2c6c8da..2fe95e3c 100644
--- a/packages/shared/src/homebox.test.ts
+++ b/packages/shared/src/homebox.test.ts
@@ -131,6 +131,11 @@ describe('looksLikeBox', () => {
'Thùng đồ',
'Giỏ đồ chơi',
'Vật chứa xanh',
+ '箱 01',
+ '1号箱',
+ '纸箱 2',
+ '厨房收纳箱',
+ '玩具收纳筐',
])('reads %s as a box', (name) => {
expect(looksLikeBox(name)).toBe(true);
});
@@ -168,6 +173,10 @@ describe('looksLikeBox', () => {
'Tủ',
'Vật dụng',
'Phòng chứa',
+ '厨房',
+ '抽屉 2', // a drawer
+ '冰箱', // a fridge, not a box
+ '保险箱', // a safe
])('reads %s as a place', (name) => {
expect(looksLikeBox(name)).toBe(false);
});
diff --git a/packages/shared/src/homebox.ts b/packages/shared/src/homebox.ts
index 70089dd7..52a584b6 100644
--- a/packages/shared/src/homebox.ts
+++ b/packages/shared/src/homebox.ts
@@ -130,8 +130,38 @@ export const BOX_WORDS: readonly string[] = Object.freeze([
'cestas',
'canasta',
'canastas',
+ // Simplified Chinese
+ '箱',
+ '号箱',
+ '纸箱',
+ '收纳箱',
+ '储物箱',
+ '整理箱',
+ '周转箱',
+ '搬家箱',
+ '塑料箱',
+ '木箱',
+ '收纳盒',
+ '储物盒',
+ '收纳筐',
+ '收纳篮',
]);
const BOX_WORD_SET = new Set(BOX_WORDS);
+const ZH_BOX_SUFFIXES = [
+ '纸箱',
+ '收纳箱',
+ '储物箱',
+ '整理箱',
+ '周转箱',
+ '搬家箱',
+ '塑料箱',
+ '木箱',
+ '收纳盒',
+ '储物盒',
+ '收纳筐',
+ '收纳篮',
+ '号箱',
+] as const;
/** A box word followed by one of these isn't a box: "caja registradora" is a till (#474). */
const NOT_A_BOX_AFTER: Readonly> = Object.freeze({
@@ -153,6 +183,8 @@ export function looksLikeBox(name: string): boolean {
previous = raw;
// Arabic's article: "الصندوق" is "صندوق".
if (raw.startsWith('ال') && BOX_WORD_SET.has(raw.slice(2))) return true;
+ // Unspaced Chinese compounds: "厨房收纳箱", "1号纸箱", "2号箱", but not "冰箱" or "抽屉".
+ if (ZH_BOX_SUFFIXES.some((s) => raw.endsWith(s))) return true;
}
return false;
}
diff --git a/packages/shared/src/language-search.test.ts b/packages/shared/src/language-search.test.ts
index 1d922319..78b50269 100644
--- a/packages/shared/src/language-search.test.ts
+++ b/packages/shared/src/language-search.test.ts
@@ -11,6 +11,7 @@ const LANGUAGES = [
];
/** One more language: its names come from Intl, so nothing here needs an entry for it. */
const WITH_UKRAINIAN = [...LANGUAGES, { id: 'uk', name: 'Українська' }];
+const WITH_CHINESE = [...LANGUAGES, { id: 'zh', name: '简体中文' }];
function find(query: string, interfaceTag = 'en', languages = LANGUAGES): string[] {
return findLanguages(languageSearch(languages, interfaceTag), query).map((l) => l.id);
@@ -49,6 +50,10 @@ describe('findLanguages', () => {
it('finds by the start of a name, for a language the list did not have before', () => {
expect(find('ukr', 'en', WITH_UKRAINIAN)).toEqual(['uk']);
expect(find('укр', 'en', WITH_UKRAINIAN)).toEqual(['uk']);
+ expect(find('中文', 'en', WITH_CHINESE)).toEqual(['zh']);
+ expect(find('简体', 'en', WITH_CHINESE)).toEqual(['zh']);
+ expect(find('chinese', 'en', WITH_CHINESE)).toEqual(['zh']);
+ expect(find('simplified', 'en', WITH_CHINESE)).toEqual(['zh']);
expect(find('ger')).toEqual(['de']);
expect(find('viet')).toEqual(['vi']);
});
diff --git a/packages/shared/src/language-search.ts b/packages/shared/src/language-search.ts
index ee775c37..4dd2c44c 100644
--- a/packages/shared/src/language-search.ts
+++ b/packages/shared/src/language-search.ts
@@ -61,10 +61,14 @@ export function languageSearch(
interfaceLanguage: string,
): LanguageSearch {
return languages.map((language) => {
- const translated = [
- displayName(language.id, 'en'),
- displayName(language.id, interfaceLanguage),
- ].filter((name) => name !== null);
+ const tags = language.id === 'zh' ? ['zh', 'zh-Hans'] : [language.id];
+ const translated = tags
+ .flatMap((tag) => [
+ displayName(tag, 'en'),
+ displayName(tag, language.id),
+ displayName(tag, interfaceLanguage),
+ ])
+ .filter((name): name is string => name !== null);
const given = translated.length > 0 ? translated : [language.id];
const folded = [language.name, ...given].map(fold);
const stems = folded.map(stripPrefixes);
diff --git a/packages/shared/src/length-units.test.ts b/packages/shared/src/length-units.test.ts
index fbc6e1df..6e5603ae 100644
--- a/packages/shared/src/length-units.test.ts
+++ b/packages/shared/src/length-units.test.ts
@@ -100,7 +100,19 @@ describe('readSpan', () => {
});
it('reads what it formatted, in every language', () => {
- for (const tag of ['ar', 'ar-u-nu-arab', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi']) {
+ for (const tag of [
+ 'ar',
+ 'ar-u-nu-arab',
+ 'de',
+ 'en',
+ 'es',
+ 'fr',
+ 'it',
+ 'uk',
+ 'vi',
+ 'zh',
+ 'zh-CN',
+ ]) {
for (const cm of [50, 381, 1000, 10_000]) {
const shown = formatSpan(cm, tag, 'imperial');
const back = readSpan(shown, tag, 'imperial');
diff --git a/packages/shared/src/length.test.ts b/packages/shared/src/length.test.ts
index 539089ac..6e4efbaf 100644
--- a/packages/shared/src/length.test.ts
+++ b/packages/shared/src/length.test.ts
@@ -91,7 +91,19 @@ describe('formatRoomSideField: the field’s number', () => {
});
/** Every display a field makes, read back, in every UI language and both Arabic digit sets. */
-const LOCALES = ['en', 'fr', 'de', 'it', 'vi', 'uk', 'es', 'ar-u-nu-arab', 'ar-u-nu-latn'];
+const LOCALES = [
+ 'en',
+ 'fr',
+ 'de',
+ 'it',
+ 'vi',
+ 'uk',
+ 'es',
+ 'zh',
+ 'zh-CN',
+ 'ar-u-nu-arab',
+ 'ar-u-nu-latn',
+];
describe('a field’s own display reads back (1.14.4 final review)', () => {
it('for every room side from 50 cm to 100 m', () => {
diff --git a/packages/shared/src/money.test.ts b/packages/shared/src/money.test.ts
index b15afd18..10551456 100644
--- a/packages/shared/src/money.test.ts
+++ b/packages/shared/src/money.test.ts
@@ -297,6 +297,8 @@ describe('formatAmount round-trips through parseAmount in every language (#474)'
'it',
'uk',
'vi',
+ 'zh',
+ 'zh-CN',
];
const amounts = ['0', '0.5', '1.234', '12.345', '1234', '12345.6789', '999999999999.9999'];
it.each(tags)('%s', (locale) => {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c0152938..e596392f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -279,6 +279,9 @@ importers:
'@ibm/plex-sans-arabic':
specifier: 1.1.0
version: 1.1.0
+ '@ibm/plex-sans-sc':
+ specifier: 1.1.0
+ version: 1.1.0
'@modelcontextprotocol/client':
specifier: 2.3.1
version: 2.3.1
@@ -1574,6 +1577,9 @@ packages:
'@ibm/plex-sans-arabic@1.1.0':
resolution: {integrity: sha512-u8wIS6szLAOFvlBjCFZmtpKIqbhuIuniG2N0J+sio8vV6INH58hP0t0QNYrSl9SZtCv2Fwb4oQGuZJY3kJ4+QA==}
+ '@ibm/plex-sans-sc@1.1.0':
+ resolution: {integrity: sha512-IkhORwgw/CrsUss7uW9Rj6KKSsGQoIyIaNWjjju/7sV7SYS3yk0c/DgZN/leIG3Co5lN/X4Or/sQaL+SdvmSIg==}
+
'@ibm/plex-sans@1.1.0':
resolution: {integrity: sha512-WPgvO6Yfj2w5YbhyAr1tv95RUz4LRJlqN+CmYvBglabXteufP1D1E9BABMde+ZIKdRbFJDoKF5eQzfhpnbgZcQ==}
@@ -7273,6 +7279,10 @@ snapshots:
dependencies:
'@ibm/telemetry-js': 1.11.0
+ '@ibm/plex-sans-sc@1.1.0':
+ dependencies:
+ '@ibm/telemetry-js': 1.11.0
+
'@ibm/plex-sans@1.1.0':
dependencies:
'@ibm/telemetry-js': 1.11.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index f340ab32..afc9a3ec 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -7,6 +7,7 @@ allowBuilds:
'@ibm/plex-mono': false
'@ibm/plex-sans': false
'@ibm/plex-sans-arabic': false
+ '@ibm/plex-sans-sc': false
esbuild: true
minimumReleaseAgeExclude:
- '@types/node@26.6.3'
diff --git a/scripts/check-i18n-extract.test.mjs b/scripts/check-i18n-extract.test.mjs
index 20883582..243d66c7 100644
--- a/scripts/check-i18n-extract.test.mjs
+++ b/scripts/check-i18n-extract.test.mjs
@@ -91,7 +91,7 @@ describe('the Spanish catalogue', () => {
// The committed catalogues themselves: no live entry has an empty translation in any
// non-English locale. An empty msgstr would show English in that language's UI.
describe('the committed catalogues', () => {
- for (const locale of ['ar', 'de', 'es', 'fr', 'it', 'uk', 'vi']) {
+ for (const locale of ['ar', 'de', 'es', 'fr', 'it', 'uk', 'vi', 'zh']) {
it(`${locale}: every msgstr is written`, () => {
const url = new URL(`../apps/web/src/locales/${locale}/messages.po`, import.meta.url);
const entries = parsePo(readFileSync(url, 'utf8'));
diff --git a/scripts/check-i18n.mjs b/scripts/check-i18n.mjs
index 0a0ab8c8..43d40c78 100644
--- a/scripts/check-i18n.mjs
+++ b/scripts/check-i18n.mjs
@@ -13,8 +13,8 @@
// And it fails when a catalogue holds the same message twice (same msgctxt and msgid): only one
// translation is compiled, so the other screen shows the wrong word.
//
-// Every language the app ships (Arabic, English, French, German, Italian, Ukrainian, Vietnamese,
-// Spanish) must be in the Lingui config, and each must be complete. A translation must also keep its source's shape: the
+// Every language the app ships (Arabic, English, French, German, Italian, Simplified Chinese,
+// Spanish, Ukrainian, Vietnamese) must be in the Lingui config, and each must be complete. A translation must also keep its source's shape: the
// same placeholders ({name}, {0}), the same numbered tags (<0>…0>) and the same number of ICU
// plurals, or the message would drop a value or break at runtime. In Ukrainian, whose `one` is also
// 21, 31 and 101, a plural's `one` branch must keep the number the other branches show.
@@ -55,7 +55,7 @@ export function compareCatalogues(extracted, catalogues, sourceLocale = 'en') {
}
/** The languages the app ships. Removing one from lingui.config.ts fails the check. */
-export const REQUIRED_LOCALES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'];
+export const REQUIRED_LOCALES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'];
/** Required locales the config doesn't list. */
export function missingLocales(configLocales) {
diff --git a/scripts/check-i18n.test.mjs b/scripts/check-i18n.test.mjs
index 1a3e3551..a09a974d 100644
--- a/scripts/check-i18n.test.mjs
+++ b/scripts/check-i18n.test.mjs
@@ -60,10 +60,10 @@ describe('compareCatalogues', () => {
});
describe('the languages the app ships', () => {
- it('requires all eight in the config', () => {
- expect(missingLocales(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'])).toEqual([]);
- expect(missingLocales(['en', 'ar'])).toEqual(['de', 'es', 'fr', 'it', 'uk', 'vi']);
- expect(missingLocales(['ar', 'de', 'en', 'fr', 'it'])).toEqual(['es', 'uk', 'vi']);
+ it('requires all nine in the config', () => {
+ expect(missingLocales(['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'])).toEqual([]);
+ expect(missingLocales(['en', 'ar'])).toEqual(['de', 'es', 'fr', 'it', 'uk', 'vi', 'zh']);
+ expect(missingLocales(['ar', 'de', 'en', 'fr', 'it'])).toEqual(['es', 'uk', 'vi', 'zh']);
});
it('flags a translation that drops a placeholder, a tag or a plural', () => {
diff --git a/scripts/ha-translations.test.mjs b/scripts/ha-translations.test.mjs
index 75c808c3..5508a308 100644
--- a/scripts/ha-translations.test.mjs
+++ b/scripts/ha-translations.test.mjs
@@ -7,10 +7,10 @@ import { describe, expect, it } from 'vitest';
// one file lacks shows the raw option name in that language.
const DIR = new URL('../homeassistant/kept/translations/', import.meta.url);
-const LANGUAGES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi'];
-// Home Assistant lists Latin American Spanish as its own language and falls back to English from
-// it, not to Spanish, so it gets the Spanish file again.
-const FILES = [...LANGUAGES, 'es-419'];
+const LANGUAGES = ['ar', 'de', 'en', 'es', 'fr', 'it', 'uk', 'vi', 'zh'];
+// Home Assistant lists Latin American Spanish and Simplified Chinese under their own tags and
+// falls back to English from them, so they get the Spanish and Chinese files again.
+const FILES = [...LANGUAGES, 'es-419', 'zh-Hans'];
const read = (lang) => readFileSync(new URL(`${lang}.yaml`, DIR), 'utf8');
/** The file's keys, from its layout (two levels of options, then `name` and `description`). */
@@ -34,8 +34,9 @@ describe('the Home Assistant option labels', () => {
expect(readdirSync(DIR).sort()).toEqual(FILES.map((lang) => `${lang}.yaml`).sort());
});
- it('say the same in Latin American Spanish as in Spanish', () => {
+ it('say the same in Latin American Spanish as in Spanish, and in zh-Hans as in zh', () => {
expect(read('es-419')).toBe(read('es'));
+ expect(read('zh-Hans')).toBe(read('zh'));
});
it.each(LANGUAGES)('%s has the same options as English', (lang) => {