diff --git a/.changeset/8754-dead-pack-keys-retired.md b/.changeset/8754-dead-pack-keys-retired.md new file mode 100644 index 0000000000..2501b5368d --- /dev/null +++ b/.changeset/8754-dead-pack-keys-retired.md @@ -0,0 +1,66 @@ +--- +'@object-ui/i18n': minor +--- + +Retire 23 measured-dead locale keys from all ten packs — two whole families and +eleven individual leaves (objectui#8754; director seat summon #22, 2026-09-12, +maintainer verbatim 「其他同意」). + +**Breaking, deliberately.** These keys no longer exist in any of the ten built-in +packs. This repository has no reader for any of them, but `@object-ui/i18n` is a +published package: an application outside this repository that calls `t()` with +one of the keys below now renders the raw key name instead of a sentence, with no +error thrown (i18next's missing-key fallback). That risk is accepted rather than +overlooked — the standing maintainer ruling is immediate retirement with no staged +window and no double-spelling grace, on the grounds that 「已发布零消费的能力不因 +沉没成本获得豁免」. + +Marked `minor` rather than `major` because this repository's fixed release group +tracks `@objectstack`'s major line; the breaking semantics are stated here instead. + +**Migration.** If you call one of these keys, supply the string yourself — pass +`defaultValue` to your `t()` call, or add the key to your own application's +resource bundle. For the two families there is a better answer than re-adding the +key, because a live surface already exists and the retired family was never wired +to it: + +- `approvals.*` — the shipping approvals UI renders through **`approvalsInbox.*`**, + a different namespace that is fully populated in all ten packs. Point at that. +- `marketplace.pricing.*` — nothing renders pricing labels in this repo at all. + There is no replacement key; author your own. + +**The two families, retired whole** (the unit of this retirement is the family: +retiring half a dead family leaves the other half looking live by contrast, and +the namespace roots are removed, not merely emptied): + +- `approvals.approve`, `approvals.approveSuccess`, `approvals.comment`, + `approvals.reject`, `approvals.rejectConfirm`, `approvals.rejectSuccess` +- `marketplace.pricing.contact-sales`, `marketplace.pricing.free`, + `marketplace.pricing.freemium`, `marketplace.pricing.paid`, + `marketplace.pricing.subscription`, `marketplace.pricing.usage-based` + +**The eleven individual leaves.** Each was held out of an earlier sweep by a +LONGER live sibling that merely contained it, until PR objectui#8753 put a +key-boundary requirement on the text probe. The sibling that actually renders is +named beside each, and every one of them is unaffected by this change: + +- `appDesigner.noNavItems` — renders as `appDesigner.noNavItemsHint` +- `appDesigner.separator` — renders as `appDesigner.separatorLabel` +- `console.objectView.groupBy` — renders as `console.objectView.groupByField` +- `console.objectView.toolbar` — the live sibling is `…toolbarEnabledCount` +- `dashboard.removeWidget` — the live string is the designer table's own + `engine.inspector.dashboard.removeWidget`, a different corpus +- `form.addItem` — likewise the designer table's `engine.form.addItem` +- `home.recent` — renders as `home.recentApps.title` +- `home.starred` — renders as `home.starredApps.title` +- `home.subtitle` — the live sibling is `home.build.subtitle` +- `sidebar.help` — renders as `sidebar.helpTooltip` +- `workspace.create` — renders as `workspace.createTitle` / `…createButton` + +**How the set was admitted.** Not from the card's body: `pnpm check:i18n-dead-keys` +was re-run on this change's own base after the objectui#9222 instrument repair, +and every key above is CONFIRMED by that run, or is NEEDS-REVIEW whose only hit is +non-liveness (a changelog line; a pin test). The retirement is pinned negatively by +`packages/i18n/src/__tests__/dead-pack-keys-retired-8754.test.ts`, because every +other i18n gate in this repo runs call site → key and none of them can see a key +coming back. diff --git a/packages/i18n/src/__tests__/dead-pack-keys-retired-8754.test.ts b/packages/i18n/src/__tests__/dead-pack-keys-retired-8754.test.ts new file mode 100644 index 0000000000..2379a89836 --- /dev/null +++ b/packages/i18n/src/__tests__/dead-pack-keys-retired-8754.test.ts @@ -0,0 +1,253 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +/** + * Twenty-three measured-dead locale keys are retired from all ten packs — + * two WHOLE families and eleven individual leaves (objectui#8754's deletion + * round, ruled by the director seat's summon #22 on 2026-09-12). + * + * ## Why this pin is NEGATIVE, and why it is needed at all + * + * Every i18n gate in this repo runs **call site -> key**, never key -> call site + * (objectui#4145's mechanism, restated by #4392, #4730, #5504 and #6310): + * + * - `scripts/check-i18n-call-site-keys.mjs` asks whether each call site's key + * resolves in `en`. A key with no call site is never visited. + * - `all-locales-key-parity.test.ts` compares the ten packs' key SETS to each + * other. One dead key present in all ten is exactly what it wants. + * - `scripts/check-i18n-en-drift.mjs` only fires when an `en` value CHANGES. + * - `scripts/check-i18n-dead-keys.mjs` IS the reverse direction, and it is + * report-only by design and wired into no workflow (objectui#4658). + * + * So any retired row can return to all ten packs with every gate green. This + * file is the only thing watching that direction for this batch. + * + * ## The admission criterion was a measurement, not this card's body + * + * The card that ordered this deletion named 25 keys. That number was not the + * input: the director's ruling is "instrument first, deletion second", and the + * instrument round (objectui#9222, `c4a1d39fe9`) landed first precisely so the + * deletion could be admitted by a re-run rather than by memory. Re-run on the + * deletion's own base, `check:i18n-dead-keys` reported 119 CONFIRMED / 239 + * NEEDS-REVIEW over 3010 pack keys, and the card's population re-measured to + * **23**, not 25 — the card had counted its eleven non-family leaves plus two + * families of six, double-counting the two leaves that belong to both sets. + * ⇒ no tier moved under anyone; the card's arithmetic was simply 13 + 6 + 6. + * + * ## The unit is the FAMILY, and both families went whole + * + * `approvals.*` (6) and `marketplace.pricing.*` (6) are retired as ROOTS, not + * as leaves — {@link RETIRED_ROOTS} asserts the namespace itself is gone. + * Retiring half a dead family leaves the other half looking live by contrast, + * which is the state this card existed to end. + * + * Both were whole under the ruling's family rule — every member CONFIRMED, or + * NEEDS-REVIEW whose only hit is non-liveness. The two NEEDS-REVIEW members had + * exactly one hit each and both were non-liveness: `approvals.rejectConfirm` in + * `packages/app-shell/CHANGELOG.md` (changelog prose about a past change) and + * `marketplace.pricing.freemium` in this directory's + * `untranslated-identity-4376.test.ts` allowlist (a pin, whose entry this round + * deleted with the key, on that file's own `workflow.*` precedent). + * + * The live surface each family was mistaken for is a DIFFERENT namespace, and + * {@link SURVIVING} pins it: approvals renders through `approvalsInbox.*` + * (`RecordApprovalsPanel.tsx`, `DeclaredActionsBar.tsx`, `ApprovalsInboxPage.tsx`), + * and nothing renders pricing at all — no `marketplace.pricing.` template head + * exists and the word does not occur in the marketplace UI source. + * + * ## The eleven leaves, and the shape they share + * + * Each was held out of an earlier sweep by a LONGER live sibling that merely + * contains it, until PR objectui#8753 put a key-boundary requirement on both + * sides of the text probe. `sidebar.help` was demoted by `sidebar.helpTooltip`; + * `form.addItem` by the designer table's `engine.form.addItem`; + * `workspace.create` — the purest case — by a VS Code API call + * (`vscode.workspace.createFileSystemWatcher`) that merely contains its + * characters. {@link SURVIVING} names the sibling that actually renders in each + * case, so a green here cannot be bought by deleting the neighbourhood. + * + * ## ⚠️ Why {@link SURVIVING} names only call-site-live keys + * + * Naming a key in this file makes it a TEXTUAL HIT for + * `check-i18n-dead-keys`, which would demote a CONFIRMED key to NEEDS-REVIEW — + * the self-pollution trap the sweep's own header records, and the reason this + * card's body forbids pinning keys by spelling them. A key with a real `t()` + * call site is immune: it is removed from the candidate set by the AST pass + * before the text net ever runs. + * + * So every key below was checked against the census BEFORE being named here, and + * the check is not a formality: FIVE of the obvious neighbours failed it — the + * nearest live-looking sibling in each of the `dashboard`, `form`, `sidebar`, + * `home` and `workspace` namespaces is itself CONFIRMED-dead today. Naming any + * of them would have demoted it to NEEDS-REVIEW and corrupted the next round's + * population, while this file read as diligent. + * + * ⚠️ That is not hypothetical here. A first draft of this header spelled those + * five keys out as a warning, and the post-deletion census came back 93 + * CONFIRMED where the arithmetic said 98 — the five, demoted by the very + * sentence telling the reader not to do this. The spellings are gone and the + * shape is described instead; the census then landed on 98 exactly. + * + * ⛔ Do not add a key here — in the lists below OR in this prose — without + * checking its tier first. A key name in a comment is a textual hit. + */ +import { describe, it, expect } from 'vitest'; +import { builtInLocales } from '../locales/index'; + +type LocaleCode = keyof typeof builtInLocales; +const LANGS = Object.keys(builtInLocales) as LocaleCode[]; + +const at = (pack: unknown, path: string): unknown => + path.split('.').reduce((n, k) => (n as Record | undefined)?.[k], pack); + +/** The two families, retired as whole namespaces. Roots, not leaves. */ +const RETIRED_ROOTS = ['approvals', 'marketplace.pricing'] as const; + +/** Every retired leaf, named rather than counted — six, six and eleven. */ +const RETIRED = [ + // approvals.* — the whole family. The live surface is `approvalsInbox.*`. + 'approvals.approve', + 'approvals.approveSuccess', + 'approvals.comment', + 'approvals.reject', + 'approvals.rejectConfirm', + 'approvals.rejectSuccess', + // marketplace.pricing.* — the whole family. No pricing consumer exists. + 'marketplace.pricing.contact-sales', + 'marketplace.pricing.free', + 'marketplace.pricing.freemium', + 'marketplace.pricing.paid', + 'marketplace.pricing.subscription', + 'marketplace.pricing.usage-based', + // Eleven leaves, each demoted pre-objectui#8753 by a longer live sibling. + 'appDesigner.noNavItems', + 'appDesigner.separator', + 'console.objectView.groupBy', + 'console.objectView.toolbar', + 'dashboard.removeWidget', + 'form.addItem', + 'home.recent', + 'home.starred', + 'home.subtitle', + 'sidebar.help', + 'workspace.create', +] as const; + +/** + * The keys the deletion swept AROUND — every one call-site-live, so naming it + * here cannot move its tier (see the header). These are the FIRING CONTROL on + * the deletion: they must still resolve in the same run that shows the retired + * keys gone, or "the keys are retired" is indistinguishable from "the pack + * reader broke". + */ +const SURVIVING = [ + // The live approvals surface — a different namespace, and the whole reason + // `approvals.*` read as dead. + 'approvalsInbox.loadMore', + 'approvalsInbox.overrideNotice', + 'approvalsInbox.approverUnstaffed', + // The live marketplace surface, including the sibling namespace that IS + // dynamically reached (`marketplace.category.` is a collected template head, + // which is exactly why none of that family was ever a candidate). + 'marketplace.title', + 'marketplace.load.failed', + // The longer siblings that actually render, per retired leaf. + 'appDesigner.noNavItemsHint', + 'appDesigner.separatorLabel', + 'console.objectView.configureView', + 'console.objectView.new', + 'console.objectView.save', + 'sidebar.helpTooltip', + 'sidebar.approvals', + 'workspace.createTitle', + 'workspace.createButton', + 'home.recentApps.title', + 'home.starredApps.title', + 'form.noPermissionToSave', + 'form.submitFailed', + 'dashboard.total', + 'dashboard.loading', +] as const; + +describe('objectui#8754 — the measured-dead pack keys stay retired', () => { + it('the pin covers all ten packs and a non-collapsed corpus', () => { + // Guards the premise every assertion below rests on. A pin that iterates an + // empty pack list, or asserts absence inside a pack that itself vanished, is + // green for the wrong reason — which is the single failure mode a negative + // pin cannot otherwise distinguish from success. + expect(LANGS).toHaveLength(10); + expect(RETIRED).toHaveLength(23); + expect(new Set(RETIRED).size).toBe(23); + for (const lang of LANGS) { + const size = Object.keys(builtInLocales[lang] as Record).length; + expect(size, `${lang} pack collapsed`).toBeGreaterThan(50); + } + }); + + it('no pack defines any retired key, in any of the ten packs', () => { + const revived: string[] = []; + for (const lang of LANGS) { + for (const key of RETIRED) { + if (at(builtInLocales[lang], key) !== undefined) revived.push(`${lang} :: ${key}`); + } + } + // Named, not counted: a half-reverted retirement is repaired pack by pack, + // and the repair differs per key. + expect( + revived, + 'A key retired by objectui#8754 is back in a locale pack. These 23 keys had ' + + 'no reader anywhere in the repo when they were removed — measured by ' + + '`pnpm check:i18n-dead-keys` after the objectui#9222 instrument repair, not ' + + 'assumed. Do NOT backfill one to satisfy a missing-key report: if a ' + + 'surface needs the string, author the key alongside the screen that ' + + 'renders it.', + ).toEqual([]); + }); + + it('both families are gone as ROOTS, not merely emptied leaf by leaf', () => { + // The unit of this retirement is the family. A surviving empty root would + // leave the namespace looking like a live surface with nothing in it, and + // would let a translator "restore the missing strings" into a shape that + // still type-checks. + const survivingRoots: string[] = []; + for (const lang of LANGS) { + for (const root of RETIRED_ROOTS) { + if (at(builtInLocales[lang], root) !== undefined) survivingRoots.push(`${lang} :: ${root}`); + } + } + expect(survivingRoots).toEqual([]); + }); + + it('the deletion swept around its neighbours — every survivor still resolves', () => { + // The firing control. Without it, this file's green is equally consistent + // with the packs having been emptied wholesale. + const broken: string[] = []; + for (const lang of LANGS) { + for (const key of SURVIVING) { + const value = at(builtInLocales[lang], key); + if (typeof value !== 'string' || value.trim().length === 0) { + broken.push(`${lang} :: ${key}`); + } + } + } + expect( + broken, + 'A key this retirement was supposed to sweep AROUND is missing or empty. ' + + 'These are the live siblings the retired keys were confused with — losing ' + + 'one ships a raw key name to ten locales.', + ).toEqual([]); + }); + + it('the surviving siblings are real translations, not ten copies of English', () => { + // A sample across writing systems, so "all ten packs kept the key" cannot be + // satisfied by the English string ten times — the same complement + // `objectView-config-keys-retired-4730.test.ts` carries next door. + expect(at(builtInLocales.en, 'sidebar.helpTooltip')).toBe('Help & Documentation'); + for (const lang of ['zh', 'ru', 'ar', 'ja'] as const) { + const value = at(builtInLocales[lang], 'sidebar.helpTooltip'); + expect(typeof value, `${lang} sidebar.helpTooltip`).toBe('string'); + expect(value, `${lang} sidebar.helpTooltip is the English value`).not.toBe( + at(builtInLocales.en, 'sidebar.helpTooltip'), + ); + } + }); +}); diff --git a/packages/i18n/src/__tests__/objectView-config-keys-retired-4730.test.ts b/packages/i18n/src/__tests__/objectView-config-keys-retired-4730.test.ts index 305c08140c..1396147a7c 100644 --- a/packages/i18n/src/__tests__/objectView-config-keys-retired-4730.test.ts +++ b/packages/i18n/src/__tests__/objectView-config-keys-retired-4730.test.ts @@ -97,8 +97,30 @@ const at = (pack: unknown, path: string): unknown => * since objectui#5232 added `viewConfigPermissionDenied`, the refusal shown when * a session without `manage_metadata` tries to change ORG-WIDE view config * (objectstack#7494's ruling). An ADDITION to a live namespace is not a - * regression of the retirement this file pins: none of the 116 retired keys + * regression of the retirement this file pins: none of the retired keys * came back, which is what the `it` below actually asserts. + * + * ## The objectui#8754 addition — 116 retired become 118 + * + * `groupBy` and `toolbar` joined the retired list in objectui#8754's deletion + * round, and they are here rather than in that card's own pin because THIS file + * owns the namespace's arithmetic: a `console.objectView.*` key retired anywhere + * else would move the surviving count out from under the assertions below. + * + * Both were dead all along and were held out of objectui#4730's sweep by a + * measurement defect, not by a reader. `check-i18n-dead-keys`' text net matched + * on a plain substring, so each was demoted by a LONGER live sibling that merely + * contains it — `groupBy` by `groupByField` / `groupByFieldHelp` + * (`CreateViewDialog.tsx`), `toolbar` by `toolbarEnabledCount`. PR objectui#8753 + * put a key-boundary requirement on both sides of the probe, which is what moved + * them into CONFIRMED. Note that `toolbarHint` was ALREADY retired here while + * `toolbar` was not — a split with no reason behind it, which is the shape a + * substring false-positive leaves. + * + * ⚠️ The total below stays 210 and that is deliberate: 210 is the count of keys + * that ever EXISTED in this namespace, split into a retired half that only + * grows and a surviving half that shrinks to match. A retirement moves the + * split; only a genuinely new key moves the total. */ const RETIRED_OBJECT_VIEW_KEYS = [ 'accessibility', @@ -162,6 +184,7 @@ const RETIRED_OBJECT_VIEW_KEYS = [ 'general', 'generalHint', 'gridOptionsHint', + 'groupBy', 'hiddenFields', 'hideAllFields', 'inlineEdit', @@ -204,6 +227,7 @@ const RETIRED_OBJECT_VIEW_KEYS = [ 'sortBy', 'sortsCount', 'source', + 'toolbar', 'toolbarHint', 'typeOptions', 'ufAddTab', @@ -220,20 +244,21 @@ const RETIRED_OBJECT_VIEW_KEYS = [ ] as const; /** How many keys the namespace keeps — the live + indirect-reference remainder. */ -const SURVIVING_KEY_COUNT = 94; +const SURVIVING_KEY_COUNT = 92; describe('console.objectView config-panel keys are retired (objectui#4730)', () => { it('the retired list is the measured set', () => { // Guards the premise the rest of the file rests on. If this arithmetic ever // stops holding, the assertions below are checking a set nobody chose. - expect(RETIRED_OBJECT_VIEW_KEYS).toHaveLength(116); - expect(new Set(RETIRED_OBJECT_VIEW_KEYS).size).toBe(116); + expect(RETIRED_OBJECT_VIEW_KEYS).toHaveLength(118); + expect(new Set(RETIRED_OBJECT_VIEW_KEYS).size).toBe(118); // 209 at objectui#4730's landing; 210 since objectui#5232 added - // `viewConfigPermissionDenied`. The RETIRED half is the ratchet that must - // never move — it is pinned twice above — while the surviving half is a - // live namespace that legitimately grows. Splitting them is the point: - // folding a new key into the total would be indistinguishable from a - // retired key coming back. + // `viewConfigPermissionDenied`. The RETIRED half is a ratchet that never + // runs BACKWARDS — it is pinned twice above, and objectui#8754 advanced it + // 116 -> 118 — while the surviving half is a live namespace that grows on a + // new key and shrinks by exactly what the retired half gains. Splitting + // them is the point: folding a new key into the total would be + // indistinguishable from a retired key coming back. expect(RETIRED_OBJECT_VIEW_KEYS.length + SURVIVING_KEY_COUNT).toBe(210); expect(LANGS).toHaveLength(10); }); diff --git a/packages/i18n/src/__tests__/untranslated-identity-4376.test.ts b/packages/i18n/src/__tests__/untranslated-identity-4376.test.ts index ede825ff83..3fdf1b34ac 100644 --- a/packages/i18n/src/__tests__/untranslated-identity-4376.test.ts +++ b/packages/i18n/src/__tests__/untranslated-identity-4376.test.ts @@ -102,7 +102,12 @@ const LEGITIMATE_IDENTITIES: Record = { // (no such key in `en`) — which is that guard doing its job. 'publicForm.poweredBy': 'Powered by ObjectStack — product attribution; ja keeps the English wordmark line.', 'connectAgent.apiKey.badge': 'headless — the literal mode name the CLI and API use.', - 'marketplace.pricing.freemium': 'Freemium — the pricing-tier term of art; ru keeps the loanword.', + // `marketplace.pricing.freemium` sat here until objectui#8754 retired the + // whole `marketplace.pricing.*` family as dead. Its entry went with it, on + // the same reasoning the `workflow.*` note above records: an entry is a fact + // about one key's value, so it cannot outlive the key. Both assertions in + // `keeps the allowlist honest` would have failed on a leftover entry — dead + // (no identity left to excuse) and unknown (no such key in `en`). 'console.settingsHub.beta': 'Beta — the release-stage badge, kept Latin in zh.', 'console.settingsHub.categories.Beta': 'Beta — the same badge, reached by category name.', // Pure format string: two holes and a separator, no prose to translate diff --git a/packages/i18n/src/locales/ar.ts b/packages/i18n/src/locales/ar.ts index 7e4dffb4d2..45864a9a10 100644 --- a/packages/i18n/src/locales/ar.ts +++ b/packages/i18n/src/locales/ar.ts @@ -180,7 +180,6 @@ const ar = { conflictMessage: "قام شخص آخر بتغيير هذا السجل أثناء تحريرك. الكتابة فوقه ستستبدل تغييراته بتغييراتك.", conflictLatestVersion: "وقت حفظه: {{time}}", conflictOverwrite: "الكتابة فوقه", - addItem: "إضافة عنصر", removeItem: "إزالة عنصر", fieldRequired: "هذا الحقل مطلوب", invalidFormat: "صيغة غير صالحة", @@ -1167,7 +1166,6 @@ const ar = { }, }, addWidget: "إضافة أداة", - removeWidget: "إزالة أداة", editLayout: "تعديل التخطيط", saveLayout: "حفظ التخطيط", resetLayout: "إعادة تعيين التخطيط", @@ -1305,7 +1303,6 @@ const ar = { addGroup: "إضافة مجموعة", addUrl: "إضافة URL", addSeparator: "إضافة فاصل", - noNavItems: "لا توجد عناصر تنقل بعد.", logoUrl: "Logo URL", primaryColor: "اللون الأساسي", faviconUrl: "Favicon URL", @@ -1338,7 +1335,6 @@ const ar = { stepBrandingDesc: "الشعار والألوان والأيقونة", noObjectsFound: "لم يتم العثور على كائنات.", noNavItemsHint: "لا توجد عناصر تنقل بعد. حدد كائنات في الخطوة السابقة أو أضف عناصر يدويًا.", - separator: "فاصل", separatorLabel: "— فاصل —", newGroup: "مجموعة جديدة", newLink: "رابط جديد", @@ -1896,7 +1892,6 @@ const ar = { allRecords: "جميع السجلات", new: "جديد", configureView: "تكوين العرض", - toolbar: "شريط الأدوات", toolbarEnabledCount: "{{count}} من {{total}} مفعّل", searchFields: "البحث في الحقول…", title: "العنوان", @@ -1913,7 +1908,6 @@ const ar = { longitudeField: "حقل خط الطول", imageField: "حقل الصورة", selectField: "اختر حقلاً…", - groupBy: "تجميع حسب", endDateField: "حقل تاريخ الانتهاء", import: "استيراد", importTitle: "استيراد من CSV", @@ -2285,7 +2279,6 @@ const ar = { label: "مساحات العمل", default: "مساحة العمل الخاصة بي", switch: "تبديل مساحة العمل", - create: "إنشاء مساحة عمل", createTitle: "إنشاء مساحة عمل", createDescription: "مساحة العمل هي مساحة مشتركة لفريقك للتعاون.", createButton: "إنشاء مساحة عمل", @@ -2310,7 +2303,6 @@ const ar = { packageManagement: "إدارة الحزم", searchNavigation: "البحث في التنقل…", settings: "الإعدادات", - help: "المساعدة", helpTooltip: "المساعدة والوثائق", activityFeed: "موجز النشاط", notifications: "الإشعارات", @@ -2384,7 +2376,6 @@ const ar = { capabilityWarn: "فحص التأليف: {{count}} مرجع(مراجع) قدرات لا تشير إلى شيء.", }, title: "الرئيسية", - subtitle: "لوحة تحكم مساحة العمل", nav: "الرئيسية", allApps: "جميع التطبيقات", yourApps: "تطبيقاتك", @@ -2396,8 +2387,6 @@ const ar = { empty: "لقد أنجزت كل شيء", }, loading: "جارٍ تحميل مساحة العمل…", - recent: "الأخيرة", - starred: "المميزة بنجمة", welcome: "مرحباً بك في ObjectUI", welcomeDescription: "ابدأ بإنشاء تطبيقك الأول أو تكوين إعدادات النظام.", createFirstApp: "أنشئ أول تطبيق لك", @@ -3255,14 +3244,6 @@ const ar = { storage: "التخزين", other: "أخرى", }, - pricing: { - free: "مجاني", - freemium: "مجاني جزئياً", - paid: "مدفوع", - subscription: "اشتراك", - "usage-based": "حسب الاستخدام", - "contact-sales": "تواصل مع المبيعات", - }, relativeTime: { today: "اليوم", daysAgo: "منذ {{count}} ي", @@ -3270,14 +3251,6 @@ const ar = { yearsAgo: "منذ {{count}} سنة(سنوات)", }, }, - approvals: { - approve: 'الموافقة', - reject: 'رفض', - comment: 'تعليق (اختياري)', - approveSuccess: 'تمت الموافقة', - rejectSuccess: 'تم الرفض', - rejectConfirm: 'هل تريد رفض طلب الموافقة هذا؟', - }, approvalsInbox: { loadMore: 'تحميل المزيد', loadingMore: 'جارٍ التحميل…', diff --git a/packages/i18n/src/locales/de.ts b/packages/i18n/src/locales/de.ts index ed9c0eeed5..4855f7bdde 100644 --- a/packages/i18n/src/locales/de.ts +++ b/packages/i18n/src/locales/de.ts @@ -176,7 +176,6 @@ const de = { conflictMessage: "Dieser Datensatz wurde während Ihrer Bearbeitung von jemand anderem geändert. Beim Überschreiben werden dessen Änderungen durch Ihre ersetzt.", conflictLatestVersion: "Deren Speicherung: {{time}}", conflictOverwrite: "Überschreiben", - addItem: "Element hinzufügen", removeItem: "Element entfernen", fieldRequired: "Dieses Feld ist erforderlich", invalidFormat: "Ungültiges Format", @@ -1160,7 +1159,6 @@ const de = { }, }, addWidget: "Widget hinzufügen", - removeWidget: "Widget entfernen", editLayout: "Layout bearbeiten", saveLayout: "Layout speichern", resetLayout: "Layout zurücksetzen", @@ -1298,7 +1296,6 @@ const de = { addGroup: "Gruppe hinzufügen", addUrl: "URL hinzufügen", addSeparator: "Trenner hinzufügen", - noNavItems: "Noch keine Navigationselemente.", logoUrl: "Logo-URL", primaryColor: "Primärfarbe", faviconUrl: "Favicon-URL", @@ -1331,7 +1328,6 @@ const de = { stepBrandingDesc: "Logo, Farben und Favicon", noObjectsFound: "Keine Objekte gefunden.", noNavItemsHint: "Noch keine Navigationselemente. Wählen Sie Objekte im vorherigen Schritt aus oder fügen Sie manuell hinzu.", - separator: "Trennlinie", separatorLabel: "— Trennlinie —", newGroup: "Neue Gruppe", newLink: "Neuer Link", @@ -1889,7 +1885,6 @@ const de = { allRecords: "Alle Datensätze", new: "Neu", configureView: "Ansicht konfigurieren", - toolbar: "Symbolleiste", toolbarEnabledCount: "{{count}} von {{total}} aktiviert", searchFields: "Felder suchen…", title: "Titel", @@ -1906,7 +1901,6 @@ const de = { longitudeField: "Längengradfeld", imageField: "Bildfeld", selectField: "Feld auswählen…", - groupBy: "Gruppieren nach", endDateField: "Enddatumsfeld", import: "Importieren", importTitle: "Aus CSV importieren", @@ -2278,7 +2272,6 @@ const de = { label: "Arbeitsbereiche", default: "Mein Arbeitsbereich", switch: "Arbeitsbereich wechseln", - create: "Arbeitsbereich erstellen", createTitle: "Arbeitsbereich erstellen", createDescription: "Ein Arbeitsbereich ist ein gemeinsamer Raum für Ihr Team zur Zusammenarbeit.", createButton: "Arbeitsbereich erstellen", @@ -2303,7 +2296,6 @@ const de = { packageManagement: "Paketverwaltung", searchNavigation: "Navigation durchsuchen…", settings: "Einstellungen", - help: "Hilfe", helpTooltip: "Hilfe und Dokumentation", activityFeed: "Aktivitätsfeed", notifications: "Benachrichtigungen", @@ -2377,7 +2369,6 @@ const de = { capabilityWarn: "Autorenprüfung: {{count}} Capability-Verweis(e) verweisen ins Leere.", }, title: "Startseite", - subtitle: "Ihr Arbeitsbereich-Dashboard", nav: "Startseite", allApps: "Alle Anwendungen", yourApps: "Ihre Apps", @@ -2389,8 +2380,6 @@ const de = { empty: "Alles erledigt", }, loading: "Arbeitsbereich wird geladen…", - recent: "Kürzlich", - starred: "Mit Stern", welcome: "Willkommen bei ObjectUI", welcomeDescription: "Erstellen Sie zunächst Ihre erste Anwendung oder konfigurieren Sie Ihre Systemeinstellungen.", createFirstApp: "Erstellen Sie Ihre erste App", @@ -3248,14 +3237,6 @@ const de = { storage: "Speicher", other: "Sonstiges", }, - pricing: { - free: "Kostenlos", - freemium: "Freemium", - paid: "Kostenpflichtig", - subscription: "Abonnement", - "usage-based": "Nutzungsbasiert", - "contact-sales": "Vertrieb kontaktieren", - }, relativeTime: { today: "heute", daysAgo: "vor {{count}}d", @@ -3263,14 +3244,6 @@ const de = { yearsAgo: "vor {{count}} Jahren", }, }, - approvals: { - approve: 'Genehmigen', - reject: 'Ablehnen', - comment: 'Kommentar (optional)', - approveSuccess: 'Genehmigt', - rejectSuccess: 'Abgelehnt', - rejectConfirm: 'Diese Genehmigungsanfrage ablehnen?', - }, approvalsInbox: { loadMore: 'Mehr laden', loadingMore: 'Wird geladen…', diff --git a/packages/i18n/src/locales/en.ts b/packages/i18n/src/locales/en.ts index 2799e6f65d..1f747a42bc 100644 --- a/packages/i18n/src/locales/en.ts +++ b/packages/i18n/src/locales/en.ts @@ -194,7 +194,6 @@ const en = { form: { noPermissionToSave: "You don't have permission to save this record.", submitFailed: 'Could not save. Please try again.', - addItem: 'Add item', removeItem: 'Remove item', fieldRequired: 'This field is required', invalidFormat: 'Invalid format', @@ -1344,7 +1343,6 @@ const en = { }, dashboard: { addWidget: 'Add widget', - removeWidget: 'Remove widget', editLayout: 'Edit layout', saveLayout: 'Save layout', resetLayout: 'Reset layout', @@ -1524,7 +1522,6 @@ const en = { addGroup: 'Add Group', addUrl: 'Add URL', addSeparator: 'Add Separator', - noNavItems: 'No navigation items yet.', logoUrl: 'Logo URL', primaryColor: 'Primary Color', faviconUrl: 'Favicon URL', @@ -1557,7 +1554,6 @@ const en = { stepBrandingDesc: 'Logo, colors, and favicon', noObjectsFound: 'No objects found.', noNavItemsHint: 'No navigation items yet. Select objects in the previous step or add items manually.', - separator: 'Separator', separatorLabel: '— Separator —', newGroup: 'New Group', newLink: 'New Link', @@ -2201,7 +2197,6 @@ const en = { importedToast: 'Imported {{count}} row(s).', importedWithSkipped: 'Imported {{ok}} row(s); skipped {{skipped}}.', configureView: 'Configure View', - toolbar: 'Toolbar', toolbarEnabledCount: '{{count}} of {{total}} enabled', searchFields: 'Search fields…', title: 'Title', @@ -2273,7 +2268,6 @@ const en = { xAxisFieldHelp: 'The categorical or time dimension.', yAxisField: 'Y-axis field', yAxisFieldHelp: 'The numeric field to aggregate.', - groupBy: 'Group by', endDateField: 'End date field', ufTabs: 'Tabs', ufAddField: '+ Add filter field…', @@ -2606,7 +2600,6 @@ const en = { label: 'Workspaces', default: 'My Workspace', switch: 'Switch workspace', - create: 'Create workspace', createTitle: 'Create a workspace', createDescription: 'A workspace is a shared space for your team to collaborate.', createButton: 'Create workspace', @@ -2629,7 +2622,6 @@ const en = { }, sidebar: { settings: 'Settings', - help: 'Help', helpTooltip: 'Help & Documentation', activityFeed: 'Activity feed', notifications: 'Notifications', @@ -2669,7 +2661,6 @@ const en = { }, home: { title: 'Home', - subtitle: 'Your workspace dashboard', nav: 'Home', allApps: 'All Applications', yourApps: 'Your apps', @@ -2697,8 +2688,6 @@ const en = { }, open: 'Open', loading: 'Loading workspace…', - recent: 'Recent', - starred: 'Starred', welcome: 'Build your business system with AI', welcomeDescription: 'Describe your business in one sentence — AI generates the objects, screens, APIs and agent tools. Or start from scratch.', welcomeAdminDescription: 'Describe your business in one sentence — AI generates the objects, screens, APIs and agent tools. Or set things up yourself from the menu on the left.', @@ -3672,14 +3661,6 @@ const en = { storage: 'Storage', other: 'Other', }, - pricing: { - free: 'Free', - freemium: 'Freemium', - paid: 'Paid', - subscription: 'Subscription', - 'usage-based': 'Usage-based', - 'contact-sales': 'Contact Sales', - }, relativeTime: { today: 'today', daysAgo: '{{count}}d ago', @@ -3687,14 +3668,6 @@ const en = { yearsAgo: '{{count}}y ago', }, }, - approvals: { - approve: 'Approve', - reject: 'Reject', - comment: 'Comment (optional)', - approveSuccess: 'Approved', - rejectSuccess: 'Rejected', - rejectConfirm: 'Reject this approval request?', - }, approvalsInbox: { loadMore: 'Load more', loadingMore: 'Loading…', diff --git a/packages/i18n/src/locales/es.ts b/packages/i18n/src/locales/es.ts index 1161d3572a..26aa139e9c 100644 --- a/packages/i18n/src/locales/es.ts +++ b/packages/i18n/src/locales/es.ts @@ -180,7 +180,6 @@ const es = { conflictMessage: "Otra persona modificó este registro mientras lo editaba. Sobrescribir reemplazará sus cambios por los suyos.", conflictLatestVersion: "Su guardado: {{time}}", conflictOverwrite: "Sobrescribir", - addItem: "Añadir elemento", removeItem: "Eliminar elemento", fieldRequired: "Este campo es obligatorio", invalidFormat: "Formato no válido", @@ -1164,7 +1163,6 @@ const es = { }, }, addWidget: "Añadir widget", - removeWidget: "Eliminar widget", editLayout: "Editar diseño", saveLayout: "Guardar diseño", resetLayout: "Restablecer diseño", @@ -1302,7 +1300,6 @@ const es = { addGroup: "Agregar grupo", addUrl: "Agregar URL", addSeparator: "Agregar separador", - noNavItems: "Aún no hay elementos de navegación.", logoUrl: "URL del logo", primaryColor: "Color primario", faviconUrl: "URL del favicon", @@ -1335,7 +1332,6 @@ const es = { stepBrandingDesc: "Logo, colores y favicon", noObjectsFound: "No se encontraron objetos.", noNavItemsHint: "Aún no hay elementos de navegación. Seleccione objetos en el paso anterior o agregue elementos manualmente.", - separator: "Separador", separatorLabel: "— Separador —", newGroup: "Nuevo grupo", newLink: "Nuevo enlace", @@ -1893,7 +1889,6 @@ const es = { allRecords: "Todos los registros", new: "Nuevo", configureView: "Configurar vista", - toolbar: "Barra de herramientas", toolbarEnabledCount: "{{count}} de {{total}} habilitados", searchFields: "Buscar campos…", title: "Título", @@ -1910,7 +1905,6 @@ const es = { longitudeField: "Campo de longitud", imageField: "Campo de imagen", selectField: "Seleccionar campo…", - groupBy: "Agrupar por", endDateField: "Campo de fecha de fin", import: "Importar", importTitle: "Importar desde CSV", @@ -2282,7 +2276,6 @@ const es = { label: "Espacios de trabajo", default: "Mi espacio de trabajo", switch: "Cambiar espacio de trabajo", - create: "Crear espacio de trabajo", createTitle: "Crear un espacio de trabajo", createDescription: "Un espacio de trabajo es un lugar compartido para que tu equipo colabore.", createButton: "Crear espacio de trabajo", @@ -2307,7 +2300,6 @@ const es = { packageManagement: "Gestión de paquetes", searchNavigation: "Buscar en la navegación…", settings: "Configuración", - help: "Ayuda", helpTooltip: "Ayuda y documentación", activityFeed: "Feed de actividad", notifications: "Notificaciones", @@ -2381,7 +2373,6 @@ const es = { capabilityWarn: "Comprobación de autoría: {{count}} referencia(s) de capacidad no apuntan a nada.", }, title: "Inicio", - subtitle: "Panel de tu espacio de trabajo", nav: "Inicio", allApps: "Todas las aplicaciones", yourApps: "Tus aplicaciones", @@ -2393,8 +2384,6 @@ const es = { empty: "Estás al día", }, loading: "Cargando espacio de trabajo…", - recent: "Recientes", - starred: "Destacados", welcome: "Bienvenido a ObjectUI", welcomeDescription: "Comienza creando tu primera aplicación o configura los ajustes del sistema.", createFirstApp: "Crea tu primera aplicación", @@ -3252,14 +3241,6 @@ const es = { storage: "Almacenamiento", other: "Otro", }, - pricing: { - free: "Gratis", - freemium: "Freemium", - paid: "De pago", - subscription: "Suscripción", - "usage-based": "Por uso", - "contact-sales": "Contactar ventas", - }, relativeTime: { today: "hoy", daysAgo: "hace {{count}}d", @@ -3267,14 +3248,6 @@ const es = { yearsAgo: "hace {{count}} años", }, }, - approvals: { - approve: 'Aprobar', - reject: 'Rechazar', - comment: 'Comentario (opcional)', - approveSuccess: 'Aprobado', - rejectSuccess: 'Rechazado', - rejectConfirm: '¿Rechazar esta solicitud de aprobación?', - }, approvalsInbox: { loadMore: 'Cargar más', loadingMore: 'Cargando…', diff --git a/packages/i18n/src/locales/fr.ts b/packages/i18n/src/locales/fr.ts index 7816db10b3..6580a65573 100644 --- a/packages/i18n/src/locales/fr.ts +++ b/packages/i18n/src/locales/fr.ts @@ -176,7 +176,6 @@ const fr = { conflictMessage: "Cet enregistrement a été modifié par quelqu'un d'autre pendant votre édition. L'écrasement remplacera ses modifications par les vôtres.", conflictLatestVersion: "Son enregistrement : {{time}}", conflictOverwrite: "Écraser", - addItem: "Ajouter un élément", removeItem: "Supprimer un élément", fieldRequired: "Ce champ est obligatoire", invalidFormat: "Format invalide", @@ -1162,7 +1161,6 @@ const fr = { }, }, addWidget: "Ajouter un widget", - removeWidget: "Supprimer un widget", editLayout: "Modifier la mise en page", saveLayout: "Enregistrer la mise en page", resetLayout: "Réinitialiser la mise en page", @@ -1300,7 +1298,6 @@ const fr = { addGroup: "Ajouter un groupe", addUrl: "Ajouter une URL", addSeparator: "Ajouter un séparateur", - noNavItems: "Aucun élément de navigation pour l'instant.", logoUrl: "URL du logo", primaryColor: "Couleur principale", faviconUrl: "URL du favicon", @@ -1333,7 +1330,6 @@ const fr = { stepBrandingDesc: "Logo, couleurs et favicon", noObjectsFound: "Aucun objet trouvé.", noNavItemsHint: "Pas encore d'éléments de navigation. Sélectionnez des objets à l'étape précédente ou ajoutez-en manuellement.", - separator: "Séparateur", separatorLabel: "— Séparateur —", newGroup: "Nouveau groupe", newLink: "Nouveau lien", @@ -1891,7 +1887,6 @@ const fr = { allRecords: "Tous les enregistrements", new: "Nouveau", configureView: "Configurer la vue", - toolbar: "Barre d'outils", toolbarEnabledCount: "{{count}} sur {{total}} activés", searchFields: "Rechercher des champs…", title: "Titre", @@ -1908,7 +1903,6 @@ const fr = { longitudeField: "Champ de longitude", imageField: "Champ d'image", selectField: "Sélectionner un champ…", - groupBy: "Regrouper par", endDateField: "Champ de date de fin", import: "Importer", importTitle: "Importer depuis CSV", @@ -2280,7 +2274,6 @@ const fr = { label: "Espaces de travail", default: "Mon espace de travail", switch: "Changer d'espace de travail", - create: "Créer un espace de travail", createTitle: "Créer un espace de travail", createDescription: "Un espace de travail est un lieu partagé pour la collaboration de votre équipe.", createButton: "Créer un espace de travail", @@ -2305,7 +2298,6 @@ const fr = { packageManagement: "Gestion des packages", searchNavigation: "Rechercher dans la navigation…", settings: "Paramètres", - help: "Aide", helpTooltip: "Aide et documentation", activityFeed: "Flux d'activité", notifications: "Notifications", @@ -2379,7 +2371,6 @@ const fr = { capabilityWarn: "Contrôle de conception : {{count}} référence(s) de capacité ne mènent à rien.", }, title: "Accueil", - subtitle: "Tableau de bord de votre espace de travail", nav: "Accueil", allApps: "Toutes les applications", yourApps: "Vos applications", @@ -2391,8 +2382,6 @@ const fr = { empty: "Vous êtes à jour", }, loading: "Chargement de l'espace de travail…", - recent: "Récent", - starred: "Favoris", welcome: "Bienvenue dans ObjectUI", welcomeDescription: "Commencez par créer votre première application ou configurer les paramètres système.", createFirstApp: "Créez votre première app", @@ -3250,14 +3239,6 @@ const fr = { storage: "Stockage", other: "Autre", }, - pricing: { - free: "Gratuit", - freemium: "Freemium", - paid: "Payant", - subscription: "Abonnement", - "usage-based": "À l'utilisation", - "contact-sales": "Contacter les ventes", - }, relativeTime: { today: "aujourd'hui", daysAgo: "il y a {{count}}j", @@ -3265,14 +3246,6 @@ const fr = { yearsAgo: "il y a {{count}} ans", }, }, - approvals: { - approve: 'Approuver', - reject: 'Rejeter', - comment: 'Commentaire (facultatif)', - approveSuccess: 'Approuvé', - rejectSuccess: 'Rejeté', - rejectConfirm: 'Rejeter cette demande d’approbation ?', - }, approvalsInbox: { loadMore: 'Charger plus', loadingMore: 'Chargement…', diff --git a/packages/i18n/src/locales/ja.ts b/packages/i18n/src/locales/ja.ts index 8b8d390f13..48f2a379c3 100644 --- a/packages/i18n/src/locales/ja.ts +++ b/packages/i18n/src/locales/ja.ts @@ -176,7 +176,6 @@ const ja = { conflictMessage: "編集中にこのレコードが他のユーザーによって変更されました。上書きすると、相手の変更はあなたの内容で置き換えられます。", conflictLatestVersion: "相手の保存時刻: {{time}}", conflictOverwrite: "上書き", - addItem: "項目を追加", removeItem: "項目を削除", fieldRequired: "この項目は必須です", invalidFormat: "形式が正しくありません", @@ -1160,7 +1159,6 @@ const ja = { }, }, addWidget: "ウィジェットを追加", - removeWidget: "ウィジェットを削除", editLayout: "レイアウトを編集", saveLayout: "レイアウトを保存", resetLayout: "レイアウトをリセット", @@ -1298,7 +1296,6 @@ const ja = { addGroup: "グループを追加", addUrl: "URLを追加", addSeparator: "区切りを追加", - noNavItems: "ナビゲーション項目がありません。", logoUrl: "ロゴURL", primaryColor: "プライマリカラー", faviconUrl: "ファビコンURL", @@ -1331,7 +1328,6 @@ const ja = { stepBrandingDesc: "ロゴ、色、ファビコン", noObjectsFound: "オブジェクトが見つかりません。", noNavItemsHint: "ナビゲーション項目がありません。前のステップでオブジェクトを選択するか、手動で追加してください。", - separator: "セパレーター", separatorLabel: "— セパレーター —", newGroup: "新しいグループ", newLink: "新しいリンク", @@ -1891,7 +1887,6 @@ const ja = { allRecords: "すべてのレコード", new: "新規", configureView: "ビューを設定", - toolbar: "ツールバー", toolbarEnabledCount: "{{total}} 件中 {{count}} 件有効", searchFields: "フィールドを検索…", title: "タイトル", @@ -1908,7 +1903,6 @@ const ja = { longitudeField: "経度フィールド", imageField: "画像フィールド", selectField: "フィールドを選択…", - groupBy: "グループ化", endDateField: "終了日フィールド", import: "インポート", importTitle: "CSVからインポート", @@ -2280,7 +2274,6 @@ const ja = { label: "ワークスペース", default: "マイワークスペース", switch: "ワークスペースを切り替え", - create: "ワークスペースを作成", createTitle: "ワークスペースの作成", createDescription: "ワークスペースはチームで協力するための共有スペースです。", createButton: "ワークスペースを作成", @@ -2305,7 +2298,6 @@ const ja = { packageManagement: "パッケージ管理", searchNavigation: "ナビゲーションを検索…", settings: "設定", - help: "ヘルプ", helpTooltip: "ヘルプとドキュメント", activityFeed: "アクティビティフィード", notifications: "通知", @@ -2379,7 +2371,6 @@ const ja = { capabilityWarn: "作成時チェック:{{count}} 件のケイパビリティ参照が解決できません。", }, title: "ホーム", - subtitle: "ワークスペースのダッシュボード", nav: "ホーム", allApps: "すべてのアプリケーション", yourApps: "あなたのアプリ", @@ -2391,8 +2382,6 @@ const ja = { empty: "すべて対応済みです", }, loading: "ワークスペースを読み込み中…", - recent: "最近", - starred: "スター付き", welcome: "ObjectUI へようこそ", welcomeDescription: "最初のアプリケーションを作成するか、システム設定を行ってください。", createFirstApp: "最初のアプリを作成", @@ -3250,14 +3239,6 @@ const ja = { storage: "ストレージ", other: "その他", }, - pricing: { - free: "無料", - freemium: "フリーミアム", - paid: "有料", - subscription: "サブスクリプション", - "usage-based": "使用量ベース", - "contact-sales": "営業に問い合わせ", - }, relativeTime: { today: "今日", daysAgo: "{{count}}日前", @@ -3265,14 +3246,6 @@ const ja = { yearsAgo: "{{count}}年前", }, }, - approvals: { - approve: '承認', - reject: '却下', - comment: 'コメント(任意)', - approveSuccess: '承認しました', - rejectSuccess: '却下しました', - rejectConfirm: 'この承認リクエストを却下しますか?', - }, approvalsInbox: { loadMore: 'さらに読み込む', loadingMore: '読み込み中…', diff --git a/packages/i18n/src/locales/ko.ts b/packages/i18n/src/locales/ko.ts index 21daf67109..33d64fb428 100644 --- a/packages/i18n/src/locales/ko.ts +++ b/packages/i18n/src/locales/ko.ts @@ -176,7 +176,6 @@ const ko = { conflictMessage: "편집하는 동안 다른 사용자가 이 레코드를 변경했습니다. 덮어쓰면 상대방의 변경 내용이 내 내용으로 대체됩니다.", conflictLatestVersion: "상대방 저장 시각: {{time}}", conflictOverwrite: "덮어쓰기", - addItem: "항목 추가", removeItem: "항목 제거", fieldRequired: "이 필드는 필수입니다", invalidFormat: "형식이 올바르지 않습니다", @@ -1160,7 +1159,6 @@ const ko = { }, }, addWidget: "위젯 추가", - removeWidget: "위젯 제거", editLayout: "레이아웃 편집", saveLayout: "레이아웃 저장", resetLayout: "레이아웃 초기화", @@ -1298,7 +1296,6 @@ const ko = { addGroup: "그룹 추가", addUrl: "URL 추가", addSeparator: "구분선 추가", - noNavItems: "탐색 항목이 아직 없습니다.", logoUrl: "Logo URL", primaryColor: "기본 색상", faviconUrl: "Favicon URL", @@ -1331,7 +1328,6 @@ const ko = { stepBrandingDesc: "로고, 색상 및 파비콘", noObjectsFound: "객체를 찾을 수 없습니다.", noNavItemsHint: "네비게이션 항목이 없습니다. 이전 단계에서 객체를 선택하거나 수동으로 추가하세요.", - separator: "구분선", separatorLabel: "— 구분선 —", newGroup: "새 그룹", newLink: "새 링크", @@ -1889,7 +1885,6 @@ const ko = { allRecords: "모든 레코드", new: "새로 만들기", configureView: "뷰 구성", - toolbar: "도구 모음", toolbarEnabledCount: "{{total}}개 중 {{count}}개 활성화", searchFields: "필드 검색…", title: "제목", @@ -1906,7 +1901,6 @@ const ko = { longitudeField: "경도 필드", imageField: "이미지 필드", selectField: "필드 선택…", - groupBy: "그룹화 기준", endDateField: "종료 날짜 필드", import: "가져오기", importTitle: "CSV에서 가져오기", @@ -2278,7 +2272,6 @@ const ko = { label: "워크스페이스", default: "내 워크스페이스", switch: "워크스페이스 전환", - create: "워크스페이스 생성", createTitle: "워크스페이스 만들기", createDescription: "워크스페이스는 팀이 협업할 수 있는 공유 공간입니다.", createButton: "워크스페이스 생성", @@ -2303,7 +2296,6 @@ const ko = { packageManagement: "패키지 관리", searchNavigation: "내비게이션 검색…", settings: "설정", - help: "도움말", helpTooltip: "도움말 및 문서", activityFeed: "활동 피드", notifications: "알림", @@ -2376,7 +2368,6 @@ const ko = { capabilityWarn: "작성 검사: 기능 권한 참조 {{count}}개가 아무것도 가리키지 않습니다.", }, title: "홈", - subtitle: "워크스페이스 대시보드", nav: "홈", allApps: "모든 애플리케이션", yourApps: "내 앱", @@ -2388,8 +2379,6 @@ const ko = { empty: "모두 처리했습니다", }, loading: "워크스페이스 로드 중…", - recent: "최근", - starred: "즐겨찾기", welcome: "ObjectUI에 오신 것을 환영합니다", welcomeDescription: "첫 애플리케이션을 만들거나 시스템 설정을 구성하여 시작하세요.", createFirstApp: "첫 앱 만들기", @@ -3247,14 +3236,6 @@ const ko = { storage: "스토리지", other: "기타", }, - pricing: { - free: "무료", - freemium: "프리미엄", - paid: "유료", - subscription: "구독", - "usage-based": "사용량 기반", - "contact-sales": "영업팀 문의", - }, relativeTime: { today: "오늘", daysAgo: "{{count}}일 전", @@ -3262,14 +3243,6 @@ const ko = { yearsAgo: "{{count}}년 전", }, }, - approvals: { - approve: '승인', - reject: '반려', - comment: '의견(선택 사항)', - approveSuccess: '승인됨', - rejectSuccess: '반려됨', - rejectConfirm: '이 승인 요청을 반려하시겠습니까?', - }, approvalsInbox: { loadMore: '더 보기', loadingMore: '로딩 중…', diff --git a/packages/i18n/src/locales/pt.ts b/packages/i18n/src/locales/pt.ts index 313eb79508..9582ef9ffc 100644 --- a/packages/i18n/src/locales/pt.ts +++ b/packages/i18n/src/locales/pt.ts @@ -175,7 +175,6 @@ const pt = { conflictMessage: "Outra pessoa alterou este registro enquanto você editava. Sobrescrever substituirá as alterações dela pelas suas.", conflictLatestVersion: "Salvamento dela: {{time}}", conflictOverwrite: "Sobrescrever", - addItem: "Adicionar item", removeItem: "Remover item", fieldRequired: "Este campo é obrigatório", invalidFormat: "Formato inválido", @@ -1159,7 +1158,6 @@ const pt = { }, }, addWidget: "Adicionar widget", - removeWidget: "Remover widget", editLayout: "Editar layout", saveLayout: "Salvar layout", resetLayout: "Redefinir layout", @@ -1297,7 +1295,6 @@ const pt = { addGroup: "Adicionar grupo", addUrl: "Adicionar URL", addSeparator: "Adicionar separador", - noNavItems: "Nenhum item de navegação ainda.", logoUrl: "Logo URL", primaryColor: "Cor primária", faviconUrl: "Favicon URL", @@ -1330,7 +1327,6 @@ const pt = { stepBrandingDesc: "Logo, cores e favicon", noObjectsFound: "Nenhum objeto encontrado.", noNavItemsHint: "Sem itens de navegação. Selecione objetos na etapa anterior ou adicione manualmente.", - separator: "Separador", separatorLabel: "— Separador —", newGroup: "Novo grupo", newLink: "Novo link", @@ -1888,7 +1884,6 @@ const pt = { allRecords: "Todos os registros", new: "Novo", configureView: "Configurar visualização", - toolbar: "Barra de ferramentas", toolbarEnabledCount: "{{count}} de {{total}} habilitados", searchFields: "Pesquisar campos…", title: "Título", @@ -1905,7 +1900,6 @@ const pt = { longitudeField: "Campo de longitude", imageField: "Campo de imagem", selectField: "Selecionar campo…", - groupBy: "Agrupar por", endDateField: "Campo de data de término", import: "Importar", importTitle: "Importar do CSV", @@ -2277,7 +2271,6 @@ const pt = { label: "Espaços de trabalho", default: "Meu espaço de trabalho", switch: "Trocar de espaço de trabalho", - create: "Criar espaço de trabalho", createTitle: "Criar um espaço de trabalho", createDescription: "Um espaço de trabalho é um espaço compartilhado para colaboração da equipe.", createButton: "Criar espaço de trabalho", @@ -2302,7 +2295,6 @@ const pt = { packageManagement: "Gerenciamento de pacotes", searchNavigation: "Pesquisar na navegação…", settings: "Configurações", - help: "Ajuda", helpTooltip: "Ajuda e documentação", activityFeed: "Feed de atividades", notifications: "Notificações", @@ -2376,7 +2368,6 @@ const pt = { capabilityWarn: "Verificação de autoria: {{count}} referência(s) de capacidade não apontam para nada.", }, title: "Início", - subtitle: "Painel do seu espaço de trabalho", nav: "Início", allApps: "Todas as aplicações", yourApps: "As suas aplicações", @@ -2388,8 +2379,6 @@ const pt = { empty: "Está tudo em dia", }, loading: "Carregando espaço de trabalho…", - recent: "Recentes", - starred: "Favoritos", welcome: "Bem-vindo ao ObjectUI", welcomeDescription: "Comece criando sua primeira aplicação ou configurando as preferências do sistema.", createFirstApp: "Crie sua primeira app", @@ -3247,14 +3236,6 @@ const pt = { storage: "Armazenamento", other: "Outro", }, - pricing: { - free: "Grátis", - freemium: "Freemium", - paid: "Pago", - subscription: "Assinatura", - "usage-based": "Por uso", - "contact-sales": "Contatar vendas", - }, relativeTime: { today: "hoje", daysAgo: "há {{count}}d", @@ -3262,14 +3243,6 @@ const pt = { yearsAgo: "há {{count}} anos", }, }, - approvals: { - approve: 'Aprovar', - reject: 'Rejeitar', - comment: 'Comentário (opcional)', - approveSuccess: 'Aprovado', - rejectSuccess: 'Rejeitado', - rejectConfirm: 'Rejeitar esta solicitação de aprovação?', - }, approvalsInbox: { loadMore: 'Carregar mais', loadingMore: 'Carregando…', diff --git a/packages/i18n/src/locales/ru.ts b/packages/i18n/src/locales/ru.ts index 3ac9c11254..94d154d05e 100644 --- a/packages/i18n/src/locales/ru.ts +++ b/packages/i18n/src/locales/ru.ts @@ -182,7 +182,6 @@ const ru = { conflictMessage: "Пока вы редактировали, эту запись изменил другой пользователь. Перезапись заменит его изменения вашими.", conflictLatestVersion: "Его сохранение: {{time}}", conflictOverwrite: "Перезаписать", - addItem: "Добавить элемент", removeItem: "Удалить элемент", fieldRequired: "Это поле обязательно", invalidFormat: "Неверный формат", @@ -1170,7 +1169,6 @@ const ru = { }, }, addWidget: "Добавить виджет", - removeWidget: "Удалить виджет", editLayout: "Редактировать макет", saveLayout: "Сохранить макет", resetLayout: "Сбросить макет", @@ -1308,7 +1306,6 @@ const ru = { addGroup: "Добавить группу", addUrl: "Добавить URL", addSeparator: "Добавить разделитель", - noNavItems: "Элементов навигации пока нет.", logoUrl: "Logo URL", primaryColor: "Основной цвет", faviconUrl: "Favicon URL", @@ -1341,7 +1338,6 @@ const ru = { stepBrandingDesc: "Логотип, цвета и фавикон", noObjectsFound: "Объекты не найдены.", noNavItemsHint: "Элементов навигации пока нет. Выберите объекты на предыдущем шаге или добавьте вручную.", - separator: "Разделитель", separatorLabel: "— Разделитель —", newGroup: "Новая группа", newLink: "Новая ссылка", @@ -1901,7 +1897,6 @@ const ru = { allRecords: "Все записи", new: "Создать", configureView: "Настроить представление", - toolbar: "Панель инструментов", toolbarEnabledCount: "{{count}} из {{total}} включено", searchFields: "Поиск полей…", title: "Заголовок", @@ -1918,7 +1913,6 @@ const ru = { longitudeField: "Поле долготы", imageField: "Поле изображения", selectField: "Выберите поле…", - groupBy: "Группировать по", endDateField: "Поле даты окончания", import: "Импорт", importTitle: "Импорт из CSV", @@ -2290,7 +2284,6 @@ const ru = { label: "Рабочие пространства", default: "Моё рабочее пространство", switch: "Переключить рабочее пространство", - create: "Создать рабочее пространство", createTitle: "Создать рабочее пространство", createDescription: "Рабочее пространство — это общее место для совместной работы вашей команды.", createButton: "Создать рабочее пространство", @@ -2315,7 +2308,6 @@ const ru = { packageManagement: "Управление пакетами", searchNavigation: "Поиск по навигации…", settings: "Настройки", - help: "Помощь", helpTooltip: "Помощь и документация", activityFeed: "Лента активности", notifications: "Уведомления", @@ -2390,7 +2382,6 @@ const ru = { capabilityWarn: "Проверка при создании — несуществующих ссылок на возможности: {{count}}.", }, title: "Главная", - subtitle: "Панель вашего рабочего пространства", nav: "Главная", allApps: "Все приложения", yourApps: "Ваши приложения", @@ -2402,8 +2393,6 @@ const ru = { empty: "Всё выполнено", }, loading: "Загрузка рабочего пространства…", - recent: "Недавние", - starred: "Избранные", welcome: "Добро пожаловать в ObjectUI", welcomeDescription: "Начните с создания вашего первого приложения или настройки системы.", createFirstApp: "Создайте первое приложение", @@ -3261,14 +3250,6 @@ const ru = { storage: "Хранилище", other: "Другое", }, - pricing: { - free: "Бесплатно", - freemium: "Freemium", - paid: "Платно", - subscription: "Подписка", - "usage-based": "По использованию", - "contact-sales": "Связаться с продажами", - }, relativeTime: { today: "сегодня", daysAgo: "{{count}} д назад", @@ -3276,14 +3257,6 @@ const ru = { yearsAgo: "{{count}} лет назад", }, }, - approvals: { - approve: 'Утвердить', - reject: 'Отклонить', - comment: 'Комментарий (необязательно)', - approveSuccess: 'Утверждено', - rejectSuccess: 'Отклонено', - rejectConfirm: 'Отклонить этот запрос на согласование?', - }, approvalsInbox: { loadMore: 'Загрузить ещё', loadingMore: 'Загрузка…', diff --git a/packages/i18n/src/locales/zh.ts b/packages/i18n/src/locales/zh.ts index 1adaa509ea..3aab235a78 100644 --- a/packages/i18n/src/locales/zh.ts +++ b/packages/i18n/src/locales/zh.ts @@ -172,7 +172,6 @@ const zh = { form: { noPermissionToSave: '您没有权限保存这条记录。', submitFailed: '保存失败,请重试。', - addItem: '添加项目', removeItem: '移除项目', fieldRequired: '此字段为必填项', invalidFormat: '格式不正确', @@ -1183,7 +1182,6 @@ const zh = { }, dashboard: { addWidget: '添加组件', - removeWidget: '移除组件', editLayout: '编辑布局', saveLayout: '保存布局', resetLayout: '重置布局', @@ -1363,7 +1361,6 @@ const zh = { addGroup: '添加分组', addUrl: '添加链接', addSeparator: '添加分隔线', - noNavItems: '暂无导航项。', logoUrl: 'Logo 链接', primaryColor: '主色调', faviconUrl: '网站图标链接', @@ -1396,7 +1393,6 @@ const zh = { stepBrandingDesc: 'Logo、颜色和图标', noObjectsFound: '未找到对象。', noNavItemsHint: '暂无导航项。请在上一步选择对象或手动添加项目。', - separator: '分隔线', separatorLabel: '— 分隔线 —', newGroup: '新建分组', newLink: '新建链接', @@ -1985,7 +1981,6 @@ const zh = { importedToast: '成功导入 {{count}} 行。', importedWithSkipped: '已导入 {{ok}} 行;跳过 {{skipped}} 行。', configureView: '配置视图', - toolbar: '工具栏', toolbarEnabledCount: '已启用 {{count}}/{{total}} 项', searchFields: '搜索字段…', title: '标题', @@ -2057,7 +2052,6 @@ const zh = { xAxisFieldHelp: '用于分类或时间维度的字段。', yAxisField: 'Y 轴字段', yAxisFieldHelp: '用于数值聚合的字段。', - groupBy: '分组依据', endDateField: '结束日期字段', ufTabs: '标签页', ufAddField: '+ 添加筛选字段…', @@ -2367,7 +2361,6 @@ const zh = { label: '工作区', default: '我的工作区', switch: '切换工作区', - create: '创建工作区', createTitle: '创建工作区', createDescription: '工作区是团队协作的共享空间。', createButton: '创建工作区', @@ -2390,7 +2383,6 @@ const zh = { }, sidebar: { settings: '设置', - help: '帮助', helpTooltip: '帮助与文档', activityFeed: '活动动态', notifications: '通知', @@ -2430,7 +2422,6 @@ const zh = { }, home: { title: '首页', - subtitle: '您的工作区仪表盘', nav: '首页', allApps: '全部应用', yourApps: '我的应用', @@ -2458,8 +2449,6 @@ const zh = { }, open: '打开', loading: '正在加载工作区…', - recent: '最近使用', - starred: '收藏', welcome: '用 AI 搭建你的业务系统', welcomeDescription: '用一句话描述你的业务,AI 帮你生成对象、界面、API 和 agent 工具。也可以手动从零开始。', welcomeAdminDescription: '用一句话描述你的业务,AI 会为你生成对象、界面、API 和智能体工具;也可以从左侧菜单自行搭建。', @@ -3389,14 +3378,6 @@ const zh = { storage: '存储', other: '其他', }, - pricing: { - free: '免费', - freemium: '免费增值', - paid: '付费', - subscription: '订阅', - 'usage-based': '按用量计费', - 'contact-sales': '联系销售', - }, relativeTime: { today: '今天', daysAgo: '{{count}} 天前', @@ -3404,14 +3385,6 @@ const zh = { yearsAgo: '{{count}} 年前', }, }, - approvals: { - approve: '批准', - reject: '驳回', - comment: '审批意见(可选)', - approveSuccess: '已批准', - rejectSuccess: '已驳回', - rejectConfirm: '确定驳回该审批请求吗?', - }, approvalsInbox: { loadMore: '加载更多', loadingMore: '加载中…',