open-design/apps/landing-page/app/_lib/plugins-i18n.ts
Jane f8c860a505
feat(landing-page): localize plugins library across 18 locales (#3010)
* feat(landing-page): localize plugins library across 18 locales

PR #2926 shipped the new `/plugins/` library hub + four kind sub-routes
+ detail pages, but the chrome was English-only — visitors landing on
`/zh/plugins/` saw the old marketplace registry placeholder rendered
by the catch-all instead, and detail pages rendered identical English
copy regardless of locale prefix. This PR brings the plugin surface
to feature parity with `/zh/skills/`, `/zh/templates/`, `/zh/systems/`,
`/zh/craft/`.

## What changes

- New `app/_lib/plugins-i18n.ts` — single source for all plugin chrome
  copy (hub, list pages, chip rails, share dialog, detail-page meta
  labels). English baseline + 17 locale overrides keyed on
  `LandingLocaleCode` (the same short-code shape `localeFromPath()`
  returns). Missing keys per locale fall back to English so a
  partially-translated locale still renders sensibly. Translations
  cover hub copy, four tile titles + blurbs, seven artifact-kind
  labels + descriptions, 23 scene-subcategory labels, 18 detail-page
  chrome strings, and a six-key share-dialog table with a
  per-locale `shareTemplate({title, url})` function (translated for
  every locale where `_lib/i18n.ts` already had one — same voice).
- `app/pages/plugins/{,templates/,templates/[kind]/,skills/,systems/,
  craft/,[slug]/}/index.astro` — every hardcoded English string now
  reads `getPluginsCopy(locale)` keys. Page logic and routing
  unchanged.
- New short-code wrappers under `app/pages/[locale]/plugins/` — six
  files (hub + three sub-routes + `[kind]/` and `[slug]/`) following
  the same pattern `[locale]/skills/index.astro` already uses: each
  re-exports the canonical page component and adds a per-locale
  `getStaticPaths()` so the build emits 17 locale prefixes per
  plugin route. Total plugin-route prerender count goes from ~390 to
  ~7 000, matching the existing skill/template scaling.
- Catch-all (`[locale]/[...path].astro`) — old `getPublicPlugins` /
  `getRegistryCounts` registry rendering removed (placeholder UI
  that was never wired to a real marketplace data source). Plugin
  routes now live exclusively under `[locale]/plugins/...` short-code
  wrappers, so the catch-all stops claiming `'plugins'` as a route
  root. The dead-code path also drops a `pluginCounts.all` reference
  the title row was reading.
- `.plugins-tile-grid` styles promoted from a scoped `<style>` in the
  default-locale hub to global `app/sub-pages.css` so the
  short-code wrapper renders the same hub markup without re-mounting
  per-page CSS — `display: contents`-style scoping pitfalls in
  Astro's per-component CSS scoping made this the cleanest fix.

## Surface area

- [ ] **UI** — new page / dialog / panel / menu item / setting / empty state in `apps/web` or `apps/desktop`
- [ ] **Keyboard shortcut** — new or changed
- [ ] **CLI / env var** — new `od` subcommand or flag, new `tools-dev` flag, or new `OD_*` env var
- [ ] **API / contract** — new `/api/*` endpoint, new SSE event, or changed shape in `packages/contracts`
- [ ] **Extension point** — new entry under `skills/`, `design-systems/`, `design-templates/`, or `craft/`, or change to the skills protocol
- [ ] **i18n keys** — new translation keys (full plugin chrome added across all 18 locales)
- [ ] **New top-level dependency** — adding any new entry to the **root** `package.json`
- [ ] **Default behavior change** — changes what existing users experience without opting in
- [x] **None** — landing-page-only restoration of i18n parity for the plugin surface

## Validation

- `pnpm --filter @open-design/landing-page typecheck` → 0 errors
- `pnpm --filter @open-design/landing-page build:static` → 16 127 pages
  built (+6 584 over current main: ~388 plugin detail pages × 17
  locale prefixes plus the hub + four sub-routes × 17 locales).
- `copy-example-html.ts` reports `266 entry files + 65 referenced
  files`, identical to before — no regression in the asset-mirroring
  pipeline.
- Local Playwright smoke (`/zh/plugins/...`):
  - `/zh/plugins/` renders `<title>插件库 · Open Design</title>`,
    label `插件库`, h1 `407 个可组合的构件。`, four tiles labelled
    `模板 / 技能 / 设计系统 / 工艺`.
  - `/zh/plugins/templates/video/` renders h1 `48 视频`, scene chips
    `全部 / 动效 / 短视频 / 营销 / 产品 / 数据讲解`.
  - `/zh/plugins/example-article-magazine/` share dialog renders
    `复制下面的文案、然后跳到你想分享的平台粘贴即可` etc., share
    template auto-interpolates plugin title + URL into Chinese voice.
  - All 18 locale prefixes (`/zh`, `/zh-tw`, `/ja`, `/ko`, `/de`,
    `/fr`, `/ru`, `/es`, `/pt-br`, `/it`, `/vi`, `/pl`, `/id`, `/nl`,
    `/ar`, `/tr`, `/uk`) → 200 across hub + four sub-routes + sample
    detail page.
  - English `/plugins/` unchanged (default-locale path bypasses the
    `[locale]/...` wrapper).

* feat(landing-page): finish plugins i18n chrome across 18 locales

The first localization pass shipped a partial fix: hub headings, lead
copy, two-level page chrome, detail-page metadata labels, the share
dialog, and the chip rail were still falling back to English on every
non-English locale because plugins-i18n.ts only filled a chrome slice
for `zh` and the file header even claimed "7 artifact-kind labels and
25 scene-subcategory labels are translated" for every locale that did
not yet have those blocks.

Three changes close the visible gap:

1. plugins-i18n.ts: fills the 27 still-missing chrome fields per locale
   for zh-tw / ja / ko / de / fr / ru / es / pt-br / it / vi / pl / id /
   nl / ar / tr / uk. Includes the 7-key category map, the 23-key
   subcategory map, hubHeading / hubLead, the 4 *Label / *Heading /
   *Lead triples for the templates / skills / systems / craft hub
   pages, the 4 tile blurbs, the 4 browse buttons, sceneLabel, allChip,
   the 12 detail-page metadata labels (mode / scenario / platform /
   surface / author / manifest id / tags / preview caption / find on
   GitHub / homepage / open in new tab) and bucket label map, the
   detail share dialog (title / copy link / jump-to), and the
   header-side nav.plugins entry. zh receives the same 11 detail-page
   and share-dialog labels it was also missing.

2. header.tsx + site-footer.astro: routes the hardcoded "Plugins /
   Templates / Skills / Systems / Craft" labels through `nav.*` from
   HeaderCopy, so every locale gets its own dropdown trigger and
   footer column. Adds `nav.plugins` to HeaderCopy and fills it in 18
   locales with the local form ("插件" / "プラグイン" / "Plugins" /
   "Plug-ins" / "Plaginy" / "الإضافات" / etc).

3. plugin-row.astro + content-i18n.ts: chip rail. The bundled-plugin
   branch now runs raw `mode` / `scenario` slugs through the shared
   localizeTaxonomyValue, and that helper now also consults the
   plugins-i18n subcategory map before giving up. localizeTaxonomyValue
   now returns undefined on a true miss instead of the unknownTag
   placeholder, so chips drop quietly instead of showing "Category" /
   "分類" / "Categoría" for taxonomy slugs we have not localized yet.
   Callers that genuinely want the placeholder (`localizeContentTag`,
   blog `category`, system noun) still keep the explicit fallback.

Out of scope and tracked separately: per-plugin title and description
in plugins/_official/* (author-supplied English metadata, ~401 plugins
without an i18n schema in the manifest yet — needs RFC + tooling
before the manifests can be expanded), and adding the long tail of
mode / scenario / category slugs (`code-migration`, `plugin-sharing`,
`tune-collab`, `live-artifacts`, `engineering`, ...) to TAXONOMY_TERMS
so chips render localized labels for every taxonomy value rather than
dropping silently.

* feat(landing-page): cover plugins chip rail long-tail taxonomy slugs

PR #3010's first round localized the high-frequency mode/scenario
chips (prototype, video, image, marketing, design, ...) but left the
~37 mode/scenario and 14 category slugs that show up in real `od.*`
metadata — code-migration, plugin-sharing, design-system, planning,
scenario, refine, discovery, handoff, token-map, tune-collab, orbit,
live-artifacts, engineering, healthcare, hr, sales, support,
default-router, downstream-export, figma-migration, media-generation,
plugin-authoring, validation, 3d-shaders, animation-motion,
audio-music, creative-direction, design-systems, diagrams, documents,
image-generation, marketing-creative, screenshots, slides,
video-generation, web-artifacts, ... — falling through to undefined
and dropping their chip silently on every non-English locale.

The data layer is the source of truth here, so this expansion lands
in `content-i18n.ts:TAXONOMY_TERMS` / `CATEGORY_LABELS` rather than
the plugins-i18n catalog: a single dictionary entry per slug fans out
to every chip-rail consumer (catalog rows, detail metadata, the
templates/[kind] facets) without each consumer touching its own copy.

Translations cover all 17 non-`en` locales. Brand and product nouns
(Figma, Open Design, BYOK, plugin) stay literal; technical taxonomy
slugs get short equivalents that read as chips rather than full
prose. The result on `/ja/plugins/skills/` matches `/plugins/skills/`
chip-for-chip (30 chips both sides) instead of dropping 27 of them
the way the previous iteration did.

* feat(landing-page): read manifest title_i18n / description_i18n on bundled plugins

PR #3010's prior rounds localized chrome and chip rails but the
catalog's most prominent text — each row's plugin name and blurb —
stayed English on every non-English locale. The plugin manifest
schema (`packages/contracts/src/plugins/manifest.ts`) has supported
`title_i18n` and `description_i18n` (Record<locale, string>) on every
manifest from spec v1; ~24 of the 401 first-party manifests already
carry one for `zh-CN`. The reader was just never wired to use them.

This change does the reader half: bundled-plugins.ts captures the
two i18n maps off each `open-design.json`, plugin-row.astro and the
detail page resolve them at render time via two new helpers
(`resolveBundledTitle`, `resolveBundledDescription`) that mirror the
short→long fallback chain documented in the manifest spec
(`htmlLang` like `zh-CN` → short `LandingLocaleCode` like `zh` →
primary tag → `en` → English baseline). The static-paths pass still
runs once for all locales — it has to, since each manifest produces
one URL — but the title/description shown on the rendered page now
reads the locale off `Astro.url.pathname` and picks the right entry
out of the maps.

Verified locally: `/zh/plugins/example-card-twitter/` now reads
"Twitter 分享卡 / 推特金句 / 数据卡, 适合配推文" from the manifest's
existing `zh-CN` block instead of the English baseline.

Plugin-data half follows in a separate commit. The 17 non-English
locales × 401 manifests need backfilling so the reader has something
to resolve to; that's data, not schema, and lands as a sequence of
manifest patches rather than tangled with this code change.

* feat(plugins): translate scenarios bucket title/description across 17 locales

Closes the first chunk of #3028. Eleven scenarios plugins (the
default-scenario bundle for each taskKind: code-migration,
figma-migration, media-generation, new-generation, tune-collab,
plugin-authoring; the default design router; the React / Vue /
Next.js downstream-export starters; and the Refine baseline) get
title_i18n + description_i18n filled for all 17 non-English locales
the landing page serves (zh-CN, zh-TW, ja, ko, de, fr, ru, es,
pt-BR, it, vi, pl, id, nl, ar, tr, uk).

The reader landed in 7ddfe36; this commit is data-only. taskKind
slugs that other docs reference by name (`code-migration`,
`figma-migration`, `tune-collab`, etc.) stay literal in the
descriptions so cross-references still resolve. Brand nouns —
Open Design, Next.js, React, Vue, Figma — also stay literal.

`/ja/plugins/od-code-migration/` now reads
"コードマイグレーション(デフォルトシナリオ)" instead of the English
baseline; `/zh/plugins/skills/` shows "代码迁移(默认场景)" in the
catalog row.

Remaining buckets (image-templates 45, video-templates 50,
examples 140, design-systems 142 = 377 plugins) follow in
subsequent commits in this PR.

* fix(landing-page): drop CJK template wrap when source name is still English

The Chinese / Japanese / Korean fallback templates for craft, skill,
template, system, plugin, and blog text splice the source `name` /
`title` into a CJK sentence frame: ``${name}工艺规则``,
``Open Design 指南:${topic}``, ``${name} は…のスキルです``. When the
underlying SKILL.md / craft markdown / blog frontmatter still ships
an English name (true for ~95% of the catalog today), that produces
mid-sentence script straddling on `/zh/...`, `/zh-tw/...`, `/ja/...`,
`/ko/...` like:

  H1   : "Editorial typography hierarchy工艺规则"
  Lead : "这条 Open Design 工艺规则定义 Editorial typography hierarchy
          的执行标准…"
  Plug : "video 插件 · 3D Animated Boy Building Lego"

That reads worse than the all-English fallback, because the visitor
parses the page in two scripts at once.

Adds a `nameNeedsEnglishFallback` guard that fires for the four CJK
locales whenever the spliced-in name has no CJK characters of its
own, and threads it through every `localizeXxxText` helper:
craft, template, system, plugin, skill, blog. When it fires the
helper returns the raw English content untouched, so the section
renders end-to-end in one language. Chrome (header, footer, breadcrumb,
buttons, share dialog) keeps its CJK rendering — only the
title-and-lead block falls back.

Side benefit: the same guard kicks in on the long tail of plugin
manifests still pending `title_i18n` / `description_i18n` backfill
(tracked in #3028), so `/zh/plugins/<bundled>/` no longer pairs a
"video 插件 · 3D Animated Boy Building Lego" title with a Chinese
breadcrumb. The page reads "3D Animated Boy Building Lego" + the
English manifest description, while header / footer / breadcrumbs
stay localized. Once a manifest ships its i18n maps, the chrome and
body re-converge automatically.

Non-CJK non-Latin scripts (ar, vi, ...) keep the previous behavior —
their templates already read tolerably with English names. If that
turns out to be wrong on a real audit, the same guard generalizes by
adding the matching Unicode range and locale set.

* feat(plugins): translate image-templates bucket title/description across 17 locales

44 of 45 image-templates plugins get title_i18n + description_i18n
filled for all 17 non-English locales (zh-CN, zh-TW, ja, ko, de, fr,
ru, es, pt-BR, it, vi, pl, id, nl, ar, tr, uk). Generated via Claude
Sonnet 4.5 over the OpenRouter gateway, ~$1.38 in API spend, 156s
wall-clock. Brand and cultural references stay literal (Open Design,
Lego, Hanfu, Showa, Pokémon, Black Myth: Wukong). Long AI generation
prompts collapse to a 1-2 sentence summary capturing what the plugin
does — the description doubles as catalog blurb on the landing site,
not as the actual generation prompt (which lives in example.html /
the manifest's preview entry).

Skipped: `profile-avatar-realistically-imperfect-ai-selfie` returned
malformed JSON on three retries; will rerun with a tighter prompt in
a follow-up commit. Catalog rows for that plugin keep falling back to
the raw English fields per #3010's reader change, so nothing breaks.

Tracking: closes the image-templates row in #3028.

* feat(plugins): translate video-templates bucket title/description across 17 locales

49 of 50 video-templates plugins get title_i18n + description_i18n
filled for the 17 non-English landing locales. Generated via Claude
Sonnet 4.5 over OpenRouter, ~$1.47 in API spend, 177s wall-clock.
HyperFrames templates, the Three Kingdoms cinematic series, the
Seedance/short-film prompts, and the K-pop / wuxia / anime variants
all get a 1-2 sentence catalog blurb in each locale; brand and
cultural tokens (Black Myth: Wukong, Hanfu, Showa, Pokémon, Three
Kingdoms / 三国志, Lego, Disney, K-pop, HyperFrames) stay literal.

Skipped: `live-action-anime-adaptation-water-vs-thunder-breathing-duel`
returned malformed JSON on three retries; will rerun in followup.
Falls back to the raw English fields per the reader landed in 7ddfe36.

Tracking: closes the video-templates row in #3028.

* feat(plugins): translate examples bucket (117/140) title/description across 17 locales

117 of 140 examples plugins get title_i18n + description_i18n filled
for the 17 non-English landing locales. Generated via Claude Sonnet
4.5 over OpenRouter, $3.94 in API spend, ~13 min wall-clock at
8-way concurrency. Existing zh-CN translations on 24 manifests are
preserved (the merge keeps author-supplied entries and only adds
missing locales).

23 of 140 returned malformed JSON on three retries — the output
likely hit the 4000 max_tokens ceiling on plugins whose description
balloons across 17 locales. Those manifests fall back to English on
non-`en` rendering per the reader landed in 7ddfe36, and will rerun
in a follow-up commit with a larger token budget and a stricter
output schema.

Tracking: closes 117/140 of the examples row in #3028; the remaining
23 stay open in that issue's failure list.

* feat(plugins): translate design-systems bucket (141/142) title/description across 17 locales

141 of 142 design-systems plugins get title_i18n + description_i18n
filled for the 17 non-English landing locales. Generated via Claude
Sonnet 4.5 over OpenRouter, $2.55 in API spend, 301s wall-clock at
8-way concurrency.

Translator script gained two improvements between examples and this
bucket:
- max_tokens bumped from 4000 to 8000 so 17-locale outputs stop
  truncating on the long-tail manifests with verbose descriptions
- a balanced-brace JSON extractor that pulls the outermost `{ ... }`
  from the response, tolerating trailing prose Claude occasionally
  appends after the JSON object.

Result: only 1 manifest (`totality-festival`) failed parse this
batch, down from ~16% on the examples bucket. The next commit
re-runs the prior buckets' failures with the improved script.

Tracking: closes 141/142 of the design-systems row in #3028.

* fix(plugins): backfill 4 plugins that retried green after JSON extractor improvement

dcf-valuation, social-media-dashboard, wireframe-sketch (examples
bucket) and live-action-anime-adaptation-water-vs-thunder-breathing-duel
(video-templates bucket) parse cleanly under the balanced-brace
extractor introduced for the design-systems batch. The remaining
22 failures from the prior runs hit a different parse mode (Claude
emitting unescaped double quotes inside string values when the source
description contains its own English quotes like 'make it professional');
those will need a tighter prompt and rerun.

* fix(plugins): translate the last 22 plugins with quote-handling prompt fix

The 22 stuck plugins all carried English / Chinese double-quoted
phrases inside their description (\"make it professional\",
\"What's inside\", \"电子杂志 × 电子墨水\") that Claude was emitting
back inside JSON string values without escaping, breaking the parse.

Added one rule to the translator prompt — never use a straight double
quote inside a translated string, prefer single quotes / curly quotes
/ CJK 『 』 / 《 》 — and the previously stuck batch sailed through
clean: 22/22 ok, 0 retries, $0.85.

This closes the long tail of #3028:
- scenarios   11/11   ✓
- image-templates 45/45 ✓
- video-templates 50/50 ✓
- examples    140/140  ✓
- design-systems 142/142 ✓
- atoms       N/A (filtered from public catalog)

All 388 catalog-visible plugins now ship title_i18n + description_i18n
for all 17 non-English locales the landing page serves.

* fix(plugins): clean up four review-flagged i18n data issues

- apps/landing-page/app/_lib/plugins-i18n.ts:759 — Polish bucket
  label `examples: 'Przyklad'` was missing the diacritic; every
  other Polish string in the same block uses proper diacritics.
  Restore to 'Przykład'. (Reviewer: looper #4364985878.)

- video-templates/cinematic-route-navigation-guide — German
  title_i18n.de was a byte-for-byte copy of en ("Cinematic Route
  Navigation Guide") while the German description was already
  translated. Replace with "Cinematischer Routen-Navigationsleitfaden"
  to match the German voice the description sets.

- video-templates/hollywood-haute-couture-fantasy-video-prompt —
  Dutch title_i18n.nl was identical to en for the same reason.
  Translate the trailing noun phrase: "Hollywood Haute Couture
  Fantasy Videoprompt" (mirrors the Dutch description's compound
  word style).

- video-templates/video-seedance-three-kingdoms-guanyu-slaying-yanliang —
  Korean Hangul `돌진` had leaked into the Turkish description (a
  translation-pipeline artifact where the model copied the verb
  from the Korean output without translating it). Replace
  "saflarına돌진 eder" with the idiomatic Turkish "saflarına dalar".

All four are data-only fixes against existing manifests; no schema
changes, no reader changes. typecheck stays at 0 errors.

* fix(landing-page): localize aria-labels, alt text and BreadcrumbList JSON-LD on plugin detail page

The PR's prior rounds left six accessibility / structured-data
surfaces on `/{locale}/plugins/<slug>/` either entirely English or
mixing English chrome with the localized plugin title. Reviewer
flagged each one across multiple loops; this commit clears them all:

1. `aria-label` on the open-in-new-tab popout no longer reuses the
   visible label `pcopy.detailOpenInNewTab` (which carries the
   decorative `↗`). Added `detailOpenInNewTabAria` — same wording,
   no glyph — and the `<a aria-label>` consumes that key. The
   visible link text still ends in `↗`.

2. `<nav class="breadcrumb" aria-label="Breadcrumb">` now reads
   `aria-label={pcopy.breadcrumbLabel}`. Eighteen locales filled
   ("面包屑导航", "パンくずリスト", "Brotkrumen-Navigation",
   "Fil d'Ariane", "مسار التنقل", "İçerik haritası", ...).

3. Share-dialog `<button aria-label="Close">` now reads
   `aria-label={pcopy.shareDialogClose}`. Eighteen locales filled
   ("关闭", "閉じる", "Cerrar", "Закрыть", "إغلاق", ...).

4. Three template-literal a11y strings (`${pluginTitle} preview`,
   `Open interactive preview for ${pluginTitle}`, `${pluginTitle}
   interactive preview`) become function calls
   (`pcopy.previewImageAlt(t)`, `previewSummaryAria(t)`,
   `previewIframeTitle(t)`) so the sentence frame around the
   plugin title rotates with the page locale. Two `<img alt>` call
   sites (the static preview at line 210 and the click-to-expand
   thumbnail at line 179) both consume `previewImageAlt`.

5. `BreadcrumbList` JSON-LD position-2 now reads
   `name: pcopy.hubLabel` instead of hardcoded English `"Plugins"`.
   The visible breadcrumb at line 105 already renders
   `pcopy.hubLabel`; this aligns the structured data with the
   rendered chrome on every locale.

The new function-typed keys deliberately interpolate `pluginTitle`
(which is itself locale-resolved via `resolveBundledTitle`) so the
mixed-language guard from commit 002d457 is preserved: a manifest
without a per-locale title still flows through to a coherent
single-language a11y string because `pluginTitle` falls back to
English along with the rest of the section.

apps/landing-page typecheck stays at 0 errors.

Closes reviewer threads:
- #pullrequestreview-4364985878 (Open in new tab aria)
- #pullrequestreview-4368926224 (Polish typo + plus mixed-language alt/aria)
- #4373... (BreadcrumbList JSON-LD)
- #4374... (aria-label="Close" + aria-label="Breadcrumb")

* fix(landing-page): redirect legacy fa/hu/th /plugins/ paths to canonical

When the new `/{locale}/plugins/...` short-code wrappers landed, the
legacy catch-all `pages/[locale]/[...path].astro` dropped `'plugins'`
from its `paths` list. That intentionally avoids serving stale
marketplace-registry placeholder routes for the modern landing
locales — but it also takes `/fa/plugins/`, `/hu/plugins/`, and
`/th/plugins/` from 200 to 404, because those three legacy locales
live only in the old `_lib/i18n.ts:LOCALES` set and are not part of
`LANDING_LOCALES` (the modern 18-locale list the new wrappers serve).

Three `301`s in `_redirects` send those legacy URLs to the canonical
English `/plugins/...` so SEO and inbound links keep working until
the legacy locale set is retired entirely.

Reviewer thread (#pullrequestreview-4364052045) flagged this as a
non-blocking regression across multiple loops; this commit closes it.

* ci(landing-page): add merge_group trigger so the queue can clear PRs

`landing-page-ci.yml` only fired on `pull_request` and `push:main`,
which meant the required `Validate landing page` and
`Strict PR visual tests` checks never dispatched against the
`merge_group` ref the merge queue creates. The queue then sat at
"awaiting checks" until it timed out and ejected the PR (the
deadlock observed during the 5/26 release window).

Adding a `merge_group: { types: [checks_requested] }` trigger to
the same workflow lets the queued ref reuse the existing job graph,
matching the pattern in `ci.yml` which already wires `merge_group`.

Also drops `plugins/**` into the same paths filter as `pull_request`
since the new bundled-plugins reader (commit 7ddfe364) consumes
those manifests' `title_i18n` / `description_i18n` maps and the
landing-page CI must rerun when manifest data changes.

---------

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-27 09:30:59 +00:00

1102 lines
93 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Plugins-specific i18n strings, kept separate from `_lib/i18n.ts` so
* the plugin library's chrome (hub, list pages, chip rails, share
* dialog) doesn't bloat the canonical Copy table every page already
* loads. The catch-all (`pages/[locale]/[...path].astro`) and the
* locale-prefixed detail page (`pages/[locale]/plugins/[slug]/`)
* import from here.
*
* Locale strategy:
* - English fills every key; every other locale is `Partial<...>`
* and falls back to English on miss. Translations were drafted to
* match the voice of the existing `_lib/i18n.ts` overrides for
* each locale. Long blurbs that don't have an obvious idiomatic
* translation stay in English — the catalog still reads cleanly,
* and a follow-up can polish them without rebuilding the schema.
* - 7 artifact-kind labels and 25 scene-subcategory labels are
* translated to keep the chip rails legible at a glance.
* - Share-dialog copy ports the 18-locale table from PR #2679 so
* the brand keyword "open-source Claude Design alternative" stays
* in English on every share (deliberate — see PR #2679).
*/
/*
* Locale key uses `LandingLocaleCode` (short codes — `en`, `zh`,
* `zh-tw`, `pt-br`, …) to match the rest of `app/pages/plugins/...`,
* which derives the active locale from `localeFromPath()`. The
* Cloudflare `_redirects` file maps the long-code variants
* (`/zh-CN/...` → `/zh/...`) so visitors can still land here from
* either URL shape.
*/
import type { LandingLocaleCode } from '../i18n';
const DEFAULT_LOCALE: LandingLocaleCode = 'en';
export interface PluginCategoryCopy {
label: string;
description: string;
}
export interface PluginsCopy {
hubLabel: string;
hubHeading: (n: number) => string;
hubLead: string;
tileTemplates: string;
tileSkills: string;
tileSystems: string;
tileCraft: string;
tileTemplatesBlurb: string;
tileSkillsBlurb: string;
tileSystemsBlurb: string;
tileCraftBlurb: string;
browseTemplates: string;
browseSkills: string;
browseSystems: string;
browseCraft: string;
templatesLabel: string;
templatesHeading: (n: number) => string;
templatesLead: string;
skillsLabel: string;
skillsHeading: (n: number) => string;
skillsLead: string;
systemsLabel: string;
systemsHeading: (n: number) => string;
systemsLead: string;
craftLabel: string;
craftHeading: (n: number) => string;
craftLead: string;
artifactKindLabel: string;
sceneLabel: string;
allChip: string;
category: Record<
'prototype' | 'live-artifact' | 'deck' | 'image' | 'video' | 'hyperframes' | 'audio',
PluginCategoryCopy
>;
subcategory: Record<string, string>;
// Detail page chrome
detailUseCta: string; // "Use this plugin →"
detailFindOnGithub: string; // "Find on GitHub →"
detailHomepage: string; // "Homepage ↗"
detailMode: string;
detailScenario: string;
detailPlatform: string;
detailSurface: string;
detailAuthor: string;
detailManifestId: string;
detailTags: string;
detailPreviewCaption: string;
detailClickForLivePreview: string; // "Click for live preview ↗"
detailOpenInNewTab: string; // "Open in new tab ↗" (visible label)
/**
* Accessible-name variant of {@link detailOpenInNewTab}: same meaning, no
* decorative `↗` glyph. Splitting the keys keeps screen readers from
* announcing the arrow as part of the control's name while the visible
* label keeps the visual cue. (Reviewer flag: `aria-label` should not
* embed decorative typography.)
*/
detailOpenInNewTabAria: string;
detailBucketLabel: Record<
'examples' | 'image-templates' | 'video-templates' | 'scenarios' | 'design-systems' | 'atoms',
string
>;
// A11y strings used as `aria-label` / `alt` / `<iframe title>` on the
// detail page. Anything that takes the plugin's localized title is a
// function so the surrounding sentence frame stays in the page locale
// even when the catalog row's English fallback fires.
breadcrumbLabel: string; // <nav aria-label>
shareDialogClose: string; // share dialog × button
previewImageAlt: (title: string) => string; // <img alt>
previewSummaryAria: (title: string) => string; // <summary aria-label>
previewIframeTitle: (title: string) => string; // <iframe title>
// Share dialog
shareOpen: string;
shareTitle: string;
shareLead: string;
shareCopyText: string;
shareCopyLink: string;
shareJumpTo: string;
shareTemplate: (vars: { title: string; url: string }) => string;
}
const en: PluginsCopy = {
hubLabel: 'Plugin library',
hubHeading: (n) => `${n} composable pieces.`,
hubLead:
'Open Design is built around four kinds of plugin. Templates and Skills are what your agent runs; Systems and Craft are how it stays on-brand and accessible. Pick a section to drill in, or jump straight to a slug if you already know which one you want.',
tileTemplates: 'Templates',
tileSkills: 'Skills',
tileSystems: 'Systems',
tileCraft: 'Craft',
tileTemplatesBlurb:
'Visual, runnable templates — prototypes, slides, image and video generators, motion compositions. Every entry ships an example.html so you can fork, swap data, and ship.',
tileSkillsBlurb:
'Instruction skills the agent loads mid-task — copywriting, color theory, creative direction, brainstorming. Pure SKILL.md prose; the output depends on your input.',
tileSystemsBlurb:
'Brand-anchored design systems — palette, typography, motion, voice. Snap a project to a system and every plugin output inherits the same identity.',
tileCraftBlurb:
'Brand-agnostic craft rules — accessibility, RTL, motion easing, photography ethics. Skills opt in via `od.craft.requires` so a plugin inherits the right rigour automatically.',
browseTemplates: 'Browse templates',
browseSkills: 'Browse skills',
browseSystems: 'Browse systems',
browseCraft: 'Browse craft',
templatesLabel: 'Plugins · Templates',
templatesHeading: (n) => `${n} runnable templates.`,
templatesLead:
'Every template ships a working preview — the catalog rows thumbnail comes straight from the manifest poster the agent uses inside the product. Browse all of them below, or jump to one of the seven artifact kinds.',
skillsLabel: 'Plugins · Skills',
skillsHeading: (n) => `${n} instruction skills.`,
skillsLead:
'Skills the agent loads mid-task — copywriting, color theory, creative direction, brainstorming. Theres no static demo because the outcome depends on your input, so each detail page reads like a brief: title, description, triggers, attribution.',
systemsLabel: 'Plugins · Systems',
systemsHeading: (n) => `${n} design systems.`,
systemsLead:
'Brand-anchored design systems plugins can adopt via `od.craft.requires`. Each ships its own palette, typography, motion, and voice; snap a project to a system and every plugin output inherits the same identity.',
craftLabel: 'Plugins · Craft',
craftHeading: (n) => `${n} craft principles.`,
craftLead:
'Brand-agnostic craft rules — accessibility, RTL, motion easing, photography ethics. Skills opt in via `od.craft.requires` so a plugin inherits the right rigour automatically.',
artifactKindLabel: 'Artifact kind',
sceneLabel: 'Scene',
allChip: 'All',
category: {
prototype: {
label: 'Prototype',
description:
'Interactive product mockups — dashboards, apps, landing pages, internal tools. Anything youd hand a stakeholder and click through.',
},
'live-artifact': {
label: 'Live Artifact',
description:
'Refreshable, data-aware artifacts that re-render whenever the underlying data changes. Live dashboards, monitoring boards, recurring trackers.',
},
deck: {
label: 'Slides',
description:
'Polished slide decks from a narrative brief — pitch decks, course modules, weekly reports, product launches.',
},
image: {
label: 'Image',
description:
'Image assets generated from structured creative direction — UI mockups, brand visuals, storyboards, social posts, illustrations.',
},
video: {
label: 'Video',
description:
'Video prompts, storyboards, and render-ready motion artifacts — short-form social, marketing cuts, motion graphics, cinematic stories.',
},
hyperframes: {
label: 'HyperFrames',
description:
'HyperFrames-ready motion compositions — agent-built video that blends template HTML with frame-level keyframes.',
},
audio: {
label: 'Audio',
description:
'Audio, voice, and sound-design assets generated from a brief — podcast intros, jingles, ambient beds.',
},
},
subcategory: {
'business-dashboards': 'Dashboards',
'app-prototypes': 'Apps',
'landing-marketing': 'Landing & marketing',
'developer-tools': 'Developer tools',
'docs-reports': 'Docs & reports',
'brand-design': 'Brand & design',
'pitch-business': 'Pitch & business',
'course-training': 'Course & training',
'reports-briefings': 'Reports & briefings',
'product-sales': 'Product & sales',
'engineering-talks': 'Engineering talks',
'creative-decks': 'Creative decks',
'ui-product-mockups': 'UI & product mockups',
'brand-visuals': 'Brand & logo',
'storyboards-motion-refs': 'Storyboards',
'social-content': 'Social & content',
'avatar-portrait': 'Avatar & portrait',
'illustration-style': 'Illustration & style',
'motion-effects': 'Motion & effects',
'social-short-form': 'Social short form',
'marketing-product': 'Marketing & product',
'data-explainers': 'Data & explainers',
'cinematic-story': 'Cinematic story',
},
detailUseCta: 'Use this plugin →',
detailFindOnGithub: 'Find on GitHub →',
detailHomepage: 'Homepage ↗',
detailMode: 'Mode',
detailScenario: 'Scenario',
detailPlatform: 'Platform',
detailSurface: 'Surface',
detailAuthor: 'Author',
detailManifestId: 'Manifest id',
detailTags: 'Tags',
detailPreviewCaption: 'Preview from the bundled-plugin manifest.',
detailClickForLivePreview: 'Click for live preview ↗',
detailOpenInNewTab: 'Open in new tab ↗',
detailOpenInNewTabAria: 'Open in new tab',
detailBucketLabel: {
examples: 'Example',
'image-templates': 'Image template',
'video-templates': 'Video template',
scenarios: 'Scenario',
'design-systems': 'Design system',
atoms: 'Atom',
},
breadcrumbLabel: 'Breadcrumb',
shareDialogClose: 'Close',
previewImageAlt: (title) => `${title} preview`,
previewSummaryAria: (title) => `Open interactive preview for ${title}`,
previewIframeTitle: (title) => `${title} interactive preview`,
shareOpen: 'Share ↗',
shareTitle: 'Share this plugin',
shareLead:
'Copy the message below, then jump to the platform you want to share on and paste.',
shareCopyText: 'Copy text',
shareCopyLink: 'Copy link only',
shareJumpTo: 'Then jump to:',
shareTemplate: ({ title, url }) =>
`🎨 Just discovered ${title} on @opendesignai — the open-source Claude Design alternative.
✨ Local-first · BYOK · your agent does the design.
${url}`,
};
const overrides: Partial<Record<LandingLocaleCode, Partial<PluginsCopy>>> = {
zh: {
hubLabel: '插件库',
hubHeading: (n) => `${n} 个可组合的构件。`,
hubLead:
'Open Design 围绕四类插件构建Templates 与 Skills 是 agent 真正运行的内容Systems 与 Craft 让它保持品牌一致和可访问。点进任意一类深入查看,或直接跳到你已经知道 slug 的那一项。',
tileTemplates: '模板',
tileSkills: '技能',
tileSystems: '设计系统',
tileCraft: '工艺',
tileTemplatesBlurb:
'可视化、可运行的模板——原型、幻灯片、图像与视频生成器、动效合成。每一条都附带 example.html可以 fork、替换数据后直接交付。',
tileSkillsBlurb:
'agent 在任务中加载的指令型技能——文案、配色、创意指导、头脑风暴。纯 SKILL.md 文档,输出取决于你的输入。',
tileSystemsBlurb:
'锚定品牌的设计系统——色板、字体、动效、文风。把项目绑到某个系统,所有插件输出都会继承同一身份。',
tileCraftBlurb:
'与品牌无关的工艺规则——可访问性、RTL、动效缓动、摄影伦理。Skills 通过 `od.craft.requires` 选用,插件自动继承相应严谨度。',
browseTemplates: '浏览模板',
browseSkills: '浏览技能',
browseSystems: '浏览系统',
browseCraft: '浏览工艺',
templatesLabel: '插件 · 模板',
templatesHeading: (n) => `${n} 个可运行的模板。`,
templatesLead:
'每个模板都附带可用的预览——目录中的缩略图直接来自 agent 在产品里使用的 manifest 海报。浏览全部,或按七大产物类型筛选。',
skillsLabel: '插件 · 技能',
skillsHeading: (n) => `${n} 个指令型技能。`,
skillsLead:
'agent 在任务中加载的技能——文案、配色、创意指导、头脑风暴。没有静态 demo输出取决于你的输入所以每个详情页像一份简报标题、描述、触发词、出处。',
systemsLabel: '插件 · 设计系统',
systemsHeading: (n) => `${n} 个设计系统。`,
systemsLead:
'插件可通过 `od.craft.requires` 采用的品牌设计系统。每个系统自带色板、字体、动效与文风;把项目绑到某个系统,所有插件输出都会继承同一身份。',
craftLabel: '插件 · 工艺',
craftHeading: (n) => `${n} 条工艺规则。`,
craftLead:
'与品牌无关的工艺规则——可访问性、RTL、动效缓动、摄影伦理。Skills 通过 `od.craft.requires` 选用,插件自动继承相应严谨度。',
artifactKindLabel: '产物类型',
sceneLabel: '场景',
allChip: '全部',
category: {
prototype: { label: '原型', description: '交互式产品稿——仪表盘、应用、落地页、内部工具。任何能交给 stakeholder 点击的东西。' },
'live-artifact': { label: '实时产物', description: '可刷新、感知数据的产物,底层数据变化时自动重新渲染。实时仪表盘、监控板、周期跟踪。' },
deck: { label: '幻灯片', description: '从叙事简报生成的精致 deck——融资 deck、课程模块、周报、产品发布。' },
image: { label: '图像', description: '从结构化创意指令生成的图像——UI 稿、品牌视觉、分镜、社媒、插画。' },
video: { label: '视频', description: '视频提示词、分镜与可渲染的动态产物——短视频、营销片段、动效图形、电影感故事。' },
hyperframes: { label: 'HyperFrames', description: 'HyperFrames 就绪的动效合成——agent 构建的视频,融合模板 HTML 与帧级关键帧。' },
audio: { label: '音频', description: '从简报生成的音频、人声与声音设计——播客片头、音乐衬底、环境音。' },
},
subcategory: {
'business-dashboards': '仪表盘', 'app-prototypes': '应用', 'landing-marketing': '落地页 / 营销',
'developer-tools': '开发者工具', 'docs-reports': '文档 / 报告', 'brand-design': '品牌 / 设计',
'pitch-business': '路演 / 商业', 'course-training': '课程 / 培训', 'reports-briefings': '报告 / 简报',
'product-sales': '产品 / 销售', 'engineering-talks': '工程演讲', 'creative-decks': '创意 deck',
'ui-product-mockups': 'UI / 产品稿', 'brand-visuals': '品牌 / Logo', 'storyboards-motion-refs': '分镜',
'social-content': '社媒 / 内容', 'avatar-portrait': '头像 / 肖像', 'illustration-style': '插画 / 风格',
'motion-effects': '动效', 'social-short-form': '短视频', 'marketing-product': '营销 / 产品',
'data-explainers': '数据讲解', 'cinematic-story': '电影感叙事',
},
detailUseCta: '使用此插件 →', detailFindOnGithub: '在 GitHub 上查看 →', detailHomepage: '主页 ↗',
detailMode: '模式', detailScenario: '场景', detailPlatform: '平台', detailSurface: '形态',
detailAuthor: '作者', detailManifestId: 'Manifest ID', detailTags: '标签',
detailPreviewCaption: '来自 bundled-plugin manifest 的预览。',
detailClickForLivePreview: '点击预览实时效果 ↗', detailOpenInNewTab: '在新标签打开 ↗',
detailBucketLabel: { examples: '示例', 'image-templates': '图像模板', 'video-templates': '视频模板', scenarios: '场景', 'design-systems': '设计系统', atoms: 'Atom' },
shareOpen: '分享 ↗', shareTitle: '分享这个插件',
shareLead: '复制下面的文案,然后跳到你想分享的平台粘贴即可。',
shareCopyText: '复制文案', shareCopyLink: '只复制链接', shareJumpTo: '跳转到:',
shareTemplate: ({ title, url }) => `🎨 安利一个:@opendesignai 上的 ${title} —— Claude Design 的开源替代品。\n✨ 本地优先 · 自带模型 · 让你自己的 agent 做设计。\n\n→ ${url}`,
detailOpenInNewTabAria: '在新标签打开',
breadcrumbLabel: '面包屑导航',
shareDialogClose: '关闭',
previewImageAlt: (title) => `${title} 预览`,
previewSummaryAria: (title) => `打开 ${title} 的互动预览`,
previewIframeTitle: (title) => `${title} 互动预览`,
},
'zh-tw': {
hubLabel: '外掛庫', hubHeading: (n) => `${n} 個可組合的元件。`,
hubLead: 'Open Design 圍繞四類外掛構建Templates 與 Skills 是 agent 真正執行的內容Systems 與 Craft 讓它保持品牌一致與可存取性。',
tileTemplates: '範本', tileSkills: '技能', tileSystems: '設計系統', tileCraft: '工藝',
browseTemplates: '瀏覽範本', browseSkills: '瀏覽技能', browseSystems: '瀏覽系統', browseCraft: '瀏覽工藝',
artifactKindLabel: '產物類型', sceneLabel: '場景', allChip: '全部',
detailUseCta: '使用此外掛 →', detailFindOnGithub: '在 GitHub 上查看 →',
detailClickForLivePreview: '點擊預覽即時效果 ↗', detailOpenInNewTab: '在新分頁開啟 ↗',
shareOpen: '分享 ↗', shareTitle: '分享這個外掛',
shareLead: '複製下面的文案,然後跳到你想分享的平台貼上即可。',
shareCopyText: '複製文案', shareCopyLink: '只複製連結', shareJumpTo: '跳轉到:',
shareTemplate: ({ title, url }) => `🎨 推薦一個:@opendesignai 上的 ${title} —— Claude Design 的開源替代品。\n✨ 本地優先 · 自帶模型 · 讓你自己的 agent 做設計。\n\n→ ${url}`,
tileTemplatesBlurb: '可視覺、可執行的模板——原型、簡報、影像與影片產生器、動效合成。每一條都附 example.htmlfork 即可換資料、出貨。',
tileSkillsBlurb: 'agent 在任務途中載入的指令技能——文案、色彩理論、創意指導、發想。純 SKILL.md 文字;產出取決於你輸入什麼。',
tileSystemsBlurb: '品牌錨定的設計系統——色票、字體、動效、語氣。把專案綁到一個系統,所有外掛產出都會繼承同一個識別。',
tileCraftBlurb: '與品牌無關的工藝規則——可達性、RTL、動效曲線、攝影倫理。技能透過 `od.craft.requires` opt-in外掛自動繼承對應的嚴謹度。',
templatesLabel: '外掛 · 模板',
templatesHeading: (n) => `${n} 個可執行模板。`,
templatesLead: '每個模板都附可運作的預覽——目錄縮圖直接來自 agent 在產品內使用的 manifest poster。可以全部瀏覽也可以跳到七種產出類型之一。',
skillsLabel: '外掛 · 技能',
skillsHeading: (n) => `${n} 個指令技能。`,
skillsLead: 'agent 任務中載入的技能——文案、色彩、創意指導、發想。沒有靜態 demo因為產出取決於你的輸入每個詳情頁讀起來像一份 brief標題、描述、觸發條件、署名。',
systemsLabel: '外掛 · 設計系統',
systemsHeading: (n) => `${n} 個設計系統。`,
systemsLead: '外掛可透過 `od.craft.requires` 採用的品牌錨定設計系統。每一個都自帶色票、字體、動效與語氣;綁定一個專案到系統,所有外掛產出都繼承同一識別。',
craftLabel: '外掛 · 工藝',
craftHeading: (n) => `${n} 條工藝原則。`,
craftLead: '與品牌無關的工藝規則——可達性、RTL、動效曲線、攝影倫理。技能透過 `od.craft.requires` opt-in外掛自動繼承相應嚴謹度。',
detailHomepage: '首頁 ↗',
detailMode: '模式',
detailScenario: '場景',
detailPlatform: '平台',
detailSurface: '表面',
detailAuthor: '作者',
detailManifestId: 'Manifest ID',
detailTags: '標籤',
detailPreviewCaption: '來自 bundled-plugin manifest 的預覽。',
detailBucketLabel: { examples: '範例', 'image-templates': '影像模板', 'video-templates': '影片模板', scenarios: '場景', 'design-systems': '設計系統', atoms: 'Atom' },
detailOpenInNewTabAria: '在新分頁開啟',
breadcrumbLabel: '麵包屑導覽',
shareDialogClose: '關閉',
previewImageAlt: (title) => `${title} 預覽`,
previewSummaryAria: (title) => `開啟 ${title} 的互動預覽`,
previewIframeTitle: (title) => `${title} 互動預覽`,
},
ja: {
hubLabel: 'プラグインライブラリ', hubHeading: (n) => `${n} 個の組み合わせ可能なパーツ。`,
tileTemplates: 'テンプレート', tileSkills: 'スキル', tileSystems: 'システム', tileCraft: 'クラフト',
browseTemplates: 'テンプレートを見る', browseSkills: 'スキルを見る', browseSystems: 'システムを見る', browseCraft: 'クラフトを見る',
artifactKindLabel: '成果物の種類', sceneLabel: 'シーン', allChip: 'すべて',
detailUseCta: 'このプラグインを使う →', detailFindOnGithub: 'GitHub で見る →',
detailClickForLivePreview: 'クリックでライブプレビュー ↗', detailOpenInNewTab: '新しいタブで開く ↗',
shareOpen: '共有 ↗', shareTitle: 'このプラグインを共有',
shareLead: '下のメッセージをコピーしてから、共有したいプラットフォームに移動して貼り付けてください。',
shareCopyText: 'テキストをコピー', shareCopyLink: 'リンクのみコピー', shareJumpTo: 'プラットフォームへ:',
shareTemplate: ({ title, url }) => `🎨 @opendesignai で ${title} を発見 —— オープンソースの Claude Design 代替。\n✨ ローカル優先 · BYOK · あなたのエージェントが設計する。\n\n→ ${url}`,
hubLead: 'Open Design は 4 種類のプラグインを軸に作られています:テンプレートとスキルは agent が実行するもの、システムとクラフトはブランドとアクセシビリティを守るもの。セクションを選んで掘り下げるか、目当ての slug が決まっているなら直接ジャンプしてください。',
tileTemplatesBlurb: 'ビジュアルで実行可能なテンプレート——プロトタイプ、スライド、画像/動画ジェネレーター、モーション合成。すべての項目に example.html が同梱されており、fork してデータを差し替えればすぐ出荷できます。',
tileSkillsBlurb: 'agent がタスク途中で読み込む指示スキル——コピー、カラーセオリー、クリエイティブディレクション、ブレスト。純粋な SKILL.md テキストで、結果はあなたの入力次第です。',
tileSystemsBlurb: 'ブランドに紐づくデザインシステム——パレット、タイポグラフィ、モーション、トーン。プロジェクトをシステムに紐づければ、すべてのプラグイン出力が同じアイデンティティを引き継ぎます。',
tileCraftBlurb: 'ブランドに依存しないクラフトルール——アクセシビリティ、RTL、モーションイージング、写真倫理。スキルは `od.craft.requires` で opt-in し、プラグインは適切な厳密さを自動的に継承します。',
templatesLabel: 'プラグイン · テンプレート',
templatesHeading: (n) => `${n} 個の実行可能テンプレート。`,
templatesLead: 'すべてのテンプレートに動作するプレビューが付属——カタログのサムネイルは、agent がプロダクト内部で使う manifest poster からそのまま取得しています。一覧を眺めるか、7 つの成果物タイプのいずれかに直接ジャンプしてください。',
skillsLabel: 'プラグイン · スキル',
skillsHeading: (n) => `${n} 個の指示スキル。`,
skillsLead: 'agent がタスク途中で読み込むスキル——コピー、カラーセオリー、クリエイティブディレクション、ブレスト。結果は入力次第のため静的 demo はありません。各詳細ページは brief のように読めます:タイトル、説明、トリガー、クレジット。',
systemsLabel: 'プラグイン · システム',
systemsHeading: (n) => `${n} 個のデザインシステム。`,
systemsLead: 'プラグインが `od.craft.requires` で採用できるブランド紐付きデザインシステム。それぞれパレット、タイポグラフィ、モーション、ボイスを持ち、プロジェクトをシステムに紐づければすべてのプラグイン出力が同じアイデンティティを引き継ぎます。',
craftLabel: 'プラグイン · クラフト',
craftHeading: (n) => `${n} 個のクラフト原則。`,
craftLead: 'ブランド非依存のクラフトルール——アクセシビリティ、RTL、モーションイージング、写真倫理。スキルは `od.craft.requires` で opt-in し、プラグインは適切な厳密さを自動継承します。',
detailHomepage: 'ホームページ ↗',
detailMode: 'モード',
detailScenario: 'シーン',
detailPlatform: 'プラットフォーム',
detailSurface: 'サーフェス',
detailAuthor: '作者',
detailManifestId: 'Manifest ID',
detailTags: 'タグ',
detailPreviewCaption: 'bundled-plugin manifest からのプレビュー。',
detailBucketLabel: { examples: 'サンプル', 'image-templates': '画像テンプレート', 'video-templates': '動画テンプレート', scenarios: 'シーン', 'design-systems': 'デザインシステム', atoms: 'Atom' },
detailOpenInNewTabAria: '新しいタブで開く',
breadcrumbLabel: 'パンくずリスト',
shareDialogClose: '閉じる',
previewImageAlt: (title) => `${title} のプレビュー`,
previewSummaryAria: (title) => `${title} のインタラクティブプレビューを開く`,
previewIframeTitle: (title) => `${title} のインタラクティブプレビュー`,
},
ko: {
hubLabel: '플러그인 라이브러리', hubHeading: (n) => `${n}개의 조합 가능한 구성요소.`,
tileTemplates: '템플릿', tileSkills: '스킬', tileSystems: '시스템', tileCraft: '크래프트',
browseTemplates: '템플릿 보기', browseSkills: '스킬 보기', browseSystems: '시스템 보기', browseCraft: '크래프트 보기',
artifactKindLabel: '산출물 종류', sceneLabel: '장면', allChip: '전체',
detailUseCta: '이 플러그인 사용 →', detailFindOnGithub: 'GitHub에서 보기 →',
detailClickForLivePreview: '클릭하여 라이브 프리뷰 ↗', detailOpenInNewTab: '새 탭에서 열기 ↗',
shareOpen: '공유 ↗', shareTitle: '이 플러그인 공유',
shareLead: '아래 메시지를 복사한 다음 공유할 플랫폼으로 이동해 붙여넣으세요.',
shareCopyText: '텍스트 복사', shareCopyLink: '링크만 복사', shareJumpTo: '플랫폼으로:',
shareTemplate: ({ title, url }) => `🎨 @opendesignai에서 ${title} 발견 —— 오픈 소스 Claude Design 대안.\n✨ 로컬 우선 · BYOK · 에이전트가 디자인합니다.\n\n→ ${url}`,
hubLead: 'Open Design은 네 가지 플러그인 종류를 중심으로 구성됩니다: 템플릿과 스킬은 agent가 실행하는 것, 시스템과 크래프트는 브랜드와 접근성을 지키는 것. 섹션을 골라 들어가거나, 원하는 slug를 알고 있다면 바로 이동하세요.',
tileTemplatesBlurb: '시각적이고 실행 가능한 템플릿——프로토타입, 슬라이드, 이미지 및 비디오 생성기, 모션 컴포지션. 모든 항목에 example.html이 포함되어 있어 fork하고 데이터만 바꾸면 바로 출시할 수 있습니다.',
tileSkillsBlurb: 'agent가 작업 중에 로드하는 지시 스킬——카피라이팅, 컬러 이론, 크리에이티브 디렉션, 브레인스토밍. 순수 SKILL.md 텍스트이며 결과는 입력에 따라 달라집니다.',
tileSystemsBlurb: '브랜드에 고정된 디자인 시스템——팔레트, 타이포그래피, 모션, 보이스. 프로젝트를 시스템에 연결하면 모든 플러그인 출력이 동일한 아이덴티티를 계승합니다.',
tileCraftBlurb: '브랜드에 무관한 크래프트 규칙——접근성, RTL, 모션 이징, 사진 윤리. 스킬은 `od.craft.requires`로 opt-in하며 플러그인이 적절한 엄밀함을 자동으로 계승합니다.',
templatesLabel: '플러그인 · 템플릿',
templatesHeading: (n) => `${n}개의 실행 가능한 템플릿.`,
templatesLead: '모든 템플릿에는 작동하는 프리뷰가 포함됩니다——카탈로그 썸네일은 agent가 제품 내에서 사용하는 manifest poster에서 바로 가져옵니다. 전체를 둘러보거나 7가지 산출물 종류 중 하나로 바로 이동하세요.',
skillsLabel: '플러그인 · 스킬',
skillsHeading: (n) => `${n}개의 지시 스킬.`,
skillsLead: 'agent가 작업 도중 로드하는 스킬——카피라이팅, 컬러 이론, 크리에이티브 디렉션, 브레인스토밍. 결과는 입력에 따라 다르므로 정적 demo가 없습니다. 각 상세 페이지는 brief처럼 읽힙니다: 제목, 설명, 트리거, 크레딧.',
systemsLabel: '플러그인 · 시스템',
systemsHeading: (n) => `${n}개의 디자인 시스템.`,
systemsLead: '플러그인이 `od.craft.requires`로 채택할 수 있는 브랜드 고정 디자인 시스템. 각자 팔레트, 타이포그래피, 모션, 보이스를 가지며 프로젝트를 시스템에 연결하면 모든 플러그인 출력이 같은 아이덴티티를 계승합니다.',
craftLabel: '플러그인 · 크래프트',
craftHeading: (n) => `${n}개의 크래프트 원칙.`,
craftLead: '브랜드 무관 크래프트 규칙——접근성, RTL, 모션 이징, 사진 윤리. 스킬은 `od.craft.requires`로 opt-in하며 플러그인이 적절한 엄밀함을 자동 계승합니다.',
detailHomepage: '홈페이지 ↗',
detailMode: '모드',
detailScenario: '장면',
detailPlatform: '플랫폼',
detailSurface: '서피스',
detailAuthor: '작성자',
detailManifestId: 'Manifest ID',
detailTags: '태그',
detailPreviewCaption: 'bundled-plugin manifest에서 가져온 프리뷰.',
detailBucketLabel: { examples: '예시', 'image-templates': '이미지 템플릿', 'video-templates': '비디오 템플릿', scenarios: '장면', 'design-systems': '디자인 시스템', atoms: 'Atom' },
detailOpenInNewTabAria: '새 탭에서 열기',
breadcrumbLabel: '경로 탐색',
shareDialogClose: '닫기',
previewImageAlt: (title) => `${title} 프리뷰`,
previewSummaryAria: (title) => `${title} 인터랙티브 프리뷰 열기`,
previewIframeTitle: (title) => `${title} 인터랙티브 프리뷰`,
},
de: {
hubLabel: 'Plugin-Bibliothek', hubHeading: (n) => `${n} kombinierbare Bausteine.`,
tileTemplates: 'Vorlagen', tileSkills: 'Skills', tileSystems: 'Systeme', tileCraft: 'Handwerk',
browseTemplates: 'Vorlagen ansehen', browseSkills: 'Skills ansehen', browseSystems: 'Systeme ansehen', browseCraft: 'Handwerk ansehen',
artifactKindLabel: 'Artefakt-Art', sceneLabel: 'Szene', allChip: 'Alle',
detailUseCta: 'Plugin nutzen →', detailFindOnGithub: 'Auf GitHub ansehen →',
detailClickForLivePreview: 'Klicken für Live-Vorschau ↗', detailOpenInNewTab: 'In neuem Tab öffnen ↗',
shareOpen: 'Teilen ↗', shareTitle: 'Diesen Plugin teilen',
shareLead: 'Kopiere die Nachricht unten und füge sie auf der gewünschten Plattform ein.',
shareCopyText: 'Text kopieren', shareCopyLink: 'Nur Link kopieren', shareJumpTo: 'Zur Plattform:',
shareTemplate: ({ title, url }) => `🎨 Gerade entdeckt: ${title} auf @opendesignai — die Open-Source-Alternative zu Claude Design.\n✨ Local-first · BYOK · dein Agent designt.\n\n→ ${url}`,
hubLead: 'Open Design ist um vier Plugin-Arten herum gebaut: Templates und Skills sind das, was dein Agent ausführt; Systems und Craft halten Marke und Zugänglichkeit. Wähle eine Sektion zum Vertiefen oder springe direkt zu einem Slug, wenn du schon weißt, welches du willst.',
tileTemplatesBlurb: 'Visuelle, lauffähige Templates — Prototypen, Slides, Bild- und Video-Generatoren, Motion-Kompositionen. Jeder Eintrag liefert eine example.html, sodass du forken, Daten austauschen und ausliefern kannst.',
tileSkillsBlurb: 'Instruktions-Skills, die der Agent mitten in einer Aufgabe lädt — Texten, Farbenlehre, Creative Direction, Brainstorming. Reine SKILL.md-Prosa; das Ergebnis hängt von deiner Eingabe ab.',
tileSystemsBlurb: 'Marken-verankerte Designsysteme — Palette, Typografie, Motion, Voice. Verbinde ein Projekt mit einem System und jedes Plugin-Output erbt dieselbe Identität.',
tileCraftBlurb: 'Markenneutrale Craft-Regeln — Barrierefreiheit, RTL, Motion-Easing, Fotografie-Ethik. Skills opten via `od.craft.requires` ein, sodass ein Plugin automatisch die richtige Strenge erbt.',
templatesLabel: 'Plugins · Templates',
templatesHeading: (n) => `${n} lauffähige Templates.`,
templatesLead: 'Jedes Template kommt mit einer funktionierenden Preview — die Thumbnails der Katalogzeilen stammen direkt aus dem Manifest-Poster, den der Agent im Produkt benutzt. Schau dir alle an oder springe zu einer der sieben Artefakt-Arten.',
skillsLabel: 'Plugins · Skills',
skillsHeading: (n) => `${n} Instruktions-Skills.`,
skillsLead: 'Skills, die der Agent während einer Aufgabe lädt — Texten, Farbenlehre, Creative Direction, Brainstorming. Es gibt keine statische Demo, weil das Ergebnis von deiner Eingabe abhängt; jede Detailseite liest sich wie ein Brief: Titel, Beschreibung, Trigger, Attribution.',
systemsLabel: 'Plugins · Systeme',
systemsHeading: (n) => `${n} Designsysteme.`,
systemsLead: 'Marken-verankerte Designsysteme, die Plugins via `od.craft.requires` übernehmen können. Jedes liefert eigene Palette, Typografie, Motion und Voice; verbinde ein Projekt mit einem System und jedes Plugin-Output erbt dieselbe Identität.',
craftLabel: 'Plugins · Gestaltung',
craftHeading: (n) => `${n} Gestaltungsprinzipien.`,
craftLead: 'Markenneutrale Craft-Regeln — Barrierefreiheit, RTL, Motion-Easing, Fotografie-Ethik. Skills opten via `od.craft.requires` ein, sodass ein Plugin automatisch die richtige Strenge erbt.',
detailHomepage: 'Homepage ↗',
detailMode: 'Modus',
detailScenario: 'Szene',
detailPlatform: 'Plattform',
detailSurface: 'Oberfläche',
detailAuthor: 'Autor',
detailManifestId: 'Manifest-ID',
detailTags: 'Tags',
detailPreviewCaption: 'Vorschau aus dem bundled-plugin Manifest.',
detailBucketLabel: { examples: 'Beispiel', 'image-templates': 'Bild-Template', 'video-templates': 'Video-Template', scenarios: 'Szene', 'design-systems': 'Designsystem', atoms: 'Atom' },
detailOpenInNewTabAria: 'In neuem Tab öffnen',
breadcrumbLabel: 'Brotkrumen-Navigation',
shareDialogClose: 'Schließen',
previewImageAlt: (title) => `${title} Vorschau`,
previewSummaryAria: (title) => `Interaktive Vorschau für ${title} öffnen`,
previewIframeTitle: (title) => `${title} Interaktive Vorschau`,
},
fr: {
hubLabel: 'Bibliothèque de plugins', hubHeading: (n) => `${n} éléments composables.`,
tileTemplates: 'Modèles', tileSkills: 'Skills', tileSystems: 'Systèmes', tileCraft: 'Artisanat',
browseTemplates: 'Parcourir les modèles', browseSkills: 'Parcourir les skills', browseSystems: 'Parcourir les systèmes', browseCraft: 'Parcourir lartisanat',
artifactKindLabel: 'Type dartefact', sceneLabel: 'Scène', allChip: 'Tous',
detailUseCta: 'Utiliser ce plugin →', detailFindOnGithub: 'Voir sur GitHub →',
detailClickForLivePreview: 'Cliquer pour aperçu en direct ↗', detailOpenInNewTab: 'Ouvrir dans un nouvel onglet ↗',
shareOpen: 'Partager ↗', shareTitle: 'Partager ce plugin',
shareLead: 'Copiez le message ci-dessous, puis ouvrez la plateforme de votre choix et collez.',
shareCopyText: 'Copier le texte', shareCopyLink: 'Copier le lien', shareJumpTo: 'Aller sur :',
shareTemplate: ({ title, url }) => `🎨 Découvert : ${title} sur @opendesignai — lalternative open-source à Claude Design.\n✨ Local-first · BYOK · votre agent fait le design.\n\n→ ${url}`,
hubLead: 'Open Design sarticule autour de quatre types de plugins : Templates et Skills sont ce que ton agent exécute ; Systems et Craft maintiennent la marque et laccessibilité. Choisis une section ou saute directement à un slug si tu sais déjà ce que tu veux.',
tileTemplatesBlurb: 'Templates visuels et exécutables — prototypes, slides, générateurs dimage et de vidéo, compositions motion. Chaque entrée embarque un example.html : forke, change les données, expédie.',
tileSkillsBlurb: 'Skills dinstruction que lagent charge en cours de tâche — copie, théorie des couleurs, direction créative, brainstorming. Pure prose SKILL.md ; le résultat dépend de ton input.',
tileSystemsBlurb: 'Design systems ancrés à la marque — palette, typographie, motion, voix. Branche un projet à un système et chaque sortie de plugin hérite de la même identité.',
tileCraftBlurb: 'Règles de craft indépendantes de la marque — accessibilité, RTL, easing motion, éthique photo. Les skills opt-in via `od.craft.requires`, et le plugin hérite automatiquement de la rigueur appropriée.',
templatesLabel: 'Plugins · Templates',
templatesHeading: (n) => `${n} templates exécutables.`,
templatesLead: 'Chaque template livre une preview fonctionnelle — la vignette du catalogue vient directement du poster de manifest utilisé par lagent dans le produit. Parcours tout, ou saute à lune des sept catégories dartefact.',
skillsLabel: 'Plugins · Skills',
skillsHeading: (n) => `${n} skills dinstruction.`,
skillsLead: 'Skills que lagent charge pendant une tâche — copie, théorie des couleurs, direction créative, brainstorming. Pas de demo statique parce que le résultat dépend de ton input ; chaque page détail se lit comme un brief : titre, description, triggers, attribution.',
systemsLabel: 'Plugins · Systèmes',
systemsHeading: (n) => `${n} design systems.`,
systemsLead: 'Design systems ancrés à la marque que les plugins peuvent adopter via `od.craft.requires`. Chacun apporte palette, typographie, motion et voix ; branche un projet à un système, chaque sortie de plugin hérite de la même identité.',
craftLabel: 'Plugins · Craft',
craftHeading: (n) => `${n} principes de craft.`,
craftLead: 'Règles de craft indépendantes de la marque — accessibilité, RTL, easing motion, éthique photo. Les skills opt-in via `od.craft.requires`, et le plugin hérite automatiquement de la rigueur appropriée.',
detailHomepage: 'Page daccueil ↗',
detailMode: 'Mode',
detailScenario: 'Scène',
detailPlatform: 'Plateforme',
detailSurface: 'Surface',
detailAuthor: 'Auteur',
detailManifestId: 'ID du manifest',
detailTags: 'Tags',
detailPreviewCaption: 'Preview depuis le manifest bundled-plugin.',
detailBucketLabel: { examples: 'Exemple', 'image-templates': 'Template image', 'video-templates': 'Template vidéo', scenarios: 'Scène', 'design-systems': 'Design system', atoms: 'Atom' },
detailOpenInNewTabAria: 'Ouvrir dans un nouvel onglet',
breadcrumbLabel: 'Fil dAriane',
shareDialogClose: 'Fermer',
previewImageAlt: (title) => `Aperçu de ${title}`,
previewSummaryAria: (title) => `Ouvrir laperçu interactif de ${title}`,
previewIframeTitle: (title) => `Aperçu interactif de ${title}`,
},
ru: {
hubLabel: 'Библиотека плагинов', hubHeading: (n) => `${n} компонуемых элементов.`,
tileTemplates: 'Шаблоны', tileSkills: 'Скиллы', tileSystems: 'Системы', tileCraft: 'Ремесло',
browseTemplates: 'Все шаблоны', browseSkills: 'Все скиллы', browseSystems: 'Все системы', browseCraft: 'Все правила ремесла',
artifactKindLabel: 'Тип артефакта', sceneLabel: 'Сцена', allChip: 'Все',
detailUseCta: 'Использовать плагин →', detailFindOnGithub: 'Посмотреть на GitHub →',
detailClickForLivePreview: 'Кликните для живого превью ↗', detailOpenInNewTab: 'Открыть в новой вкладке ↗',
shareOpen: 'Поделиться ↗', shareTitle: 'Поделиться плагином',
shareLead: 'Скопируйте сообщение ниже, затем перейдите на нужную платформу и вставьте.',
shareCopyText: 'Скопировать текст', shareCopyLink: 'Только ссылка', shareJumpTo: 'Перейти:',
shareTemplate: ({ title, url }) => `🎨 Нашёл ${title} на @opendesignai — open-source альтернативу Claude Design.\n✨ Локально · BYOK · агент сам делает дизайн.\n\n→ ${url}`,
hubLead: 'Open Design построен вокруг четырёх видов плагинов: Templates и Skills — это то, что выполняет твой agent; Systems и Craft удерживают бренд и доступность. Выбери раздел для углубления или сразу перейди по slug, если уже знаешь, что нужно.',
tileTemplatesBlurb: 'Визуальные, исполняемые шаблоны — прототипы, слайды, генераторы изображений и видео, motion-композиции. Каждая запись поставляется с example.html — форкни, замени данные, отправляй.',
tileSkillsBlurb: 'Инструкционные навыки, которые agent подгружает по ходу задачи — копирайтинг, теория цвета, креативное руководство, брейншторм. Чистый текст SKILL.md; результат зависит от твоего ввода.',
tileSystemsBlurb: 'Привязанные к бренду дизайн-системы — палитра, типографика, motion, тон. Привяжи проект к системе, и любой вывод плагина наследует ту же идентичность.',
tileCraftBlurb: 'Бренд-агностичные craft-правила — доступность, RTL, motion-easing, этика фотографии. Навыки opt-in через `od.craft.requires`, и плагин автоматически наследует нужную строгость.',
templatesLabel: 'Плагины · Шаблоны',
templatesHeading: (n) => `${n} исполняемых шаблонов.`,
templatesLead: 'Каждый шаблон поставляется с рабочей превью — миниатюра в каталоге берётся прямо из manifest poster, который agent использует внутри продукта. Пробегись по всем или прыгни в одну из семи категорий артефактов.',
skillsLabel: 'Плагины · Навыки',
skillsHeading: (n) => `${n} инструкционных навыков.`,
skillsLead: 'Навыки, которые agent подгружает в процессе задачи — копирайтинг, теория цвета, креативное руководство, брейншторм. Статичной demo нет, потому что результат зависит от ввода; каждая детальная страница читается как brief: заголовок, описание, триггеры, авторство.',
systemsLabel: 'Плагины · Системы',
systemsHeading: (n) => `${n} дизайн-систем.`,
systemsLead: 'Привязанные к бренду дизайн-системы, которые плагины могут принять через `od.craft.requires`. У каждой своя палитра, типографика, motion и тон; привяжи проект к системе — и любой вывод плагина наследует ту же идентичность.',
craftLabel: 'Плагины · Craft',
craftHeading: (n) => `${n} принципов craft.`,
craftLead: 'Бренд-агностичные craft-правила — доступность, RTL, motion-easing, этика фотографии. Навыки opt-in через `od.craft.requires`, плагин автоматически наследует нужную строгость.',
detailHomepage: 'Главная ↗',
detailMode: 'Режим',
detailScenario: 'Сцена',
detailPlatform: 'Платформа',
detailSurface: 'Поверхность',
detailAuthor: 'Автор',
detailManifestId: 'ID манифеста',
detailTags: 'Теги',
detailPreviewCaption: 'Превью из bundled-plugin манифеста.',
detailBucketLabel: { examples: 'Пример', 'image-templates': 'Шаблон изображения', 'video-templates': 'Шаблон видео', scenarios: 'Сцена', 'design-systems': 'Дизайн-система', atoms: 'Atom' },
detailOpenInNewTabAria: 'Открыть в новой вкладке',
breadcrumbLabel: 'Навигация по разделам',
shareDialogClose: 'Закрыть',
previewImageAlt: (title) => `Превью ${title}`,
previewSummaryAria: (title) => `Открыть интерактивное превью ${title}`,
previewIframeTitle: (title) => `Интерактивное превью ${title}`,
},
es: {
hubLabel: 'Biblioteca de plugins', hubHeading: (n) => `${n} piezas componibles.`,
tileTemplates: 'Plantillas', tileSkills: 'Skills', tileSystems: 'Sistemas', tileCraft: 'Oficio',
browseTemplates: 'Ver plantillas', browseSkills: 'Ver skills', browseSystems: 'Ver sistemas', browseCraft: 'Ver oficio',
artifactKindLabel: 'Tipo de artefacto', sceneLabel: 'Escena', allChip: 'Todos',
detailUseCta: 'Usar este plugin →', detailFindOnGithub: 'Ver en GitHub →',
detailClickForLivePreview: 'Clic para vista previa ↗', detailOpenInNewTab: 'Abrir en nueva pestaña ↗',
shareOpen: 'Compartir ↗', shareTitle: 'Compartir este plugin',
shareLead: 'Copia el mensaje y abre la plataforma donde quieras compartirlo.',
shareCopyText: 'Copiar texto', shareCopyLink: 'Solo el enlace', shareJumpTo: 'Ir a:',
shareTemplate: ({ title, url }) => `🎨 Acabo de descubrir ${title} en @opendesignai — la alternativa open-source a Claude Design.\n✨ Local-first · BYOK · tu agente diseña.\n\n→ ${url}`,
hubLead: 'Open Design se construye alrededor de cuatro tipos de plugin: Templates y Skills son lo que tu agent ejecuta; Systems y Craft mantienen marca y accesibilidad. Elige una sección para profundizar o salta directo a un slug si ya sabes cuál quieres.',
tileTemplatesBlurb: 'Templates visuales y ejecutables — prototipos, slides, generadores de imagen y video, composiciones motion. Cada entrada incluye un example.html: forkea, cambia los datos, despacha.',
tileSkillsBlurb: 'Skills de instrucción que el agent carga a mitad de tarea — copy, teoría del color, dirección creativa, brainstorming. Prosa pura de SKILL.md; el resultado depende de tu input.',
tileSystemsBlurb: 'Design systems anclados a la marca — paleta, tipografía, motion, voz. Conecta un proyecto a un sistema y cada salida de plugin hereda la misma identidad.',
tileCraftBlurb: 'Reglas de craft agnósticas a la marca — accesibilidad, RTL, easing de motion, ética fotográfica. Los skills opt-in con `od.craft.requires`, y el plugin hereda el rigor adecuado automáticamente.',
templatesLabel: 'Plugins · Templates',
templatesHeading: (n) => `${n} templates ejecutables.`,
templatesLead: 'Cada template trae una preview funcional — el thumbnail del catálogo viene directamente del poster del manifest que el agent usa dentro del producto. Recórrelos todos o salta a una de las siete clases de artefacto.',
skillsLabel: 'Plugins · Skills',
skillsHeading: (n) => `${n} skills de instrucción.`,
skillsLead: 'Skills que el agent carga durante una tarea — copy, teoría del color, dirección creativa, brainstorming. No hay demo estática porque el resultado depende de tu input; cada página de detalle se lee como un brief: título, descripción, triggers, atribución.',
systemsLabel: 'Plugins · Sistemas',
systemsHeading: (n) => `${n} design systems.`,
systemsLead: 'Design systems anclados a la marca que los plugins pueden adoptar vía `od.craft.requires`. Cada uno trae paleta, tipografía, motion y voz; conecta un proyecto a un sistema y cada salida de plugin hereda la misma identidad.',
craftLabel: 'Plugins · Craft',
craftHeading: (n) => `${n} principios de craft.`,
craftLead: 'Reglas de craft agnósticas a la marca — accesibilidad, RTL, easing de motion, ética fotográfica. Los skills opt-in con `od.craft.requires`, y el plugin hereda el rigor adecuado automáticamente.',
detailHomepage: 'Sitio web ↗',
detailMode: 'Modo',
detailScenario: 'Escena',
detailPlatform: 'Plataforma',
detailSurface: 'Superficie',
detailAuthor: 'Autor',
detailManifestId: 'ID del manifest',
detailTags: 'Etiquetas',
detailPreviewCaption: 'Preview del manifest bundled-plugin.',
detailBucketLabel: { examples: 'Ejemplo', 'image-templates': 'Template de imagen', 'video-templates': 'Template de video', scenarios: 'Escena', 'design-systems': 'Design system', atoms: 'Atom' },
detailOpenInNewTabAria: 'Abrir en nueva pestaña',
breadcrumbLabel: 'Ruta de navegación',
shareDialogClose: 'Cerrar',
previewImageAlt: (title) => `Vista previa de ${title}`,
previewSummaryAria: (title) => `Abrir vista previa interactiva de ${title}`,
previewIframeTitle: (title) => `Vista previa interactiva de ${title}`,
},
'pt-br': {
hubLabel: 'Biblioteca de plugins', hubHeading: (n) => `${n} peças combináveis.`,
tileTemplates: 'Templates', tileSkills: 'Skills', tileSystems: 'Sistemas', tileCraft: 'Ofício',
browseTemplates: 'Ver templates', browseSkills: 'Ver skills', browseSystems: 'Ver sistemas', browseCraft: 'Ver ofício',
artifactKindLabel: 'Tipo de artefato', sceneLabel: 'Cena', allChip: 'Todos',
detailUseCta: 'Usar este plugin →', detailFindOnGithub: 'Ver no GitHub →',
detailClickForLivePreview: 'Clique para preview ao vivo ↗', detailOpenInNewTab: 'Abrir em nova aba ↗',
shareOpen: 'Compartilhar ↗', shareTitle: 'Compartilhar este plugin',
shareLead: 'Copie a mensagem e abra a plataforma onde quer compartilhar.',
shareCopyText: 'Copiar texto', shareCopyLink: 'Só o link', shareJumpTo: 'Ir para:',
shareTemplate: ({ title, url }) => `🎨 Acabei de descobrir ${title} no @opendesignai — a alternativa open-source ao Claude Design.\n✨ Local-first · BYOK · seu agente faz o design.\n\n→ ${url}`,
hubLead: 'Open Design é construído em torno de quatro tipos de plugin: Templates e Skills são o que seu agent executa; Systems e Craft mantêm marca e acessibilidade. Escolha uma seção para se aprofundar ou pule direto para um slug se já sabe o que quer.',
tileTemplatesBlurb: 'Templates visuais e executáveis — protótipos, slides, geradores de imagem e vídeo, composições motion. Cada entrada vem com um example.html: forke, troque os dados, entregue.',
tileSkillsBlurb: 'Skills de instrução que o agent carrega no meio da tarefa — copy, teoria das cores, direção criativa, brainstorming. Pura prosa de SKILL.md; o resultado depende do seu input.',
tileSystemsBlurb: 'Design systems ancorados na marca — paleta, tipografia, motion, voz. Conecte um projeto a um sistema e toda saída de plugin herda a mesma identidade.',
tileCraftBlurb: 'Regras de craft agnósticas à marca — acessibilidade, RTL, easing de motion, ética fotográfica. Skills fazem opt-in via `od.craft.requires`, e o plugin herda o rigor adequado automaticamente.',
templatesLabel: 'Plugins · Templates',
templatesHeading: (n) => `${n} templates executáveis.`,
templatesLead: 'Cada template traz uma preview funcional — a thumbnail do catálogo vem direto do poster do manifest que o agent usa dentro do produto. Veja todos ou pule para uma das sete classes de artefato.',
skillsLabel: 'Plugins · Skills',
skillsHeading: (n) => `${n} skills de instrução.`,
skillsLead: 'Skills que o agent carrega durante uma tarefa — copy, teoria das cores, direção criativa, brainstorming. Não há demo estática porque o resultado depende do input; cada página de detalhe lê como um brief: título, descrição, triggers, atribuição.',
systemsLabel: 'Plugins · Sistemas',
systemsHeading: (n) => `${n} design systems.`,
systemsLead: 'Design systems ancorados na marca que os plugins podem adotar via `od.craft.requires`. Cada um traz paleta, tipografia, motion e voz; conecte um projeto a um sistema e toda saída de plugin herda a mesma identidade.',
craftLabel: 'Plugins · Craft',
craftHeading: (n) => `${n} princípios de craft.`,
craftLead: 'Regras de craft agnósticas à marca — acessibilidade, RTL, easing de motion, ética fotográfica. Skills fazem opt-in via `od.craft.requires`, e o plugin herda o rigor adequado automaticamente.',
detailHomepage: 'Site ↗',
detailMode: 'Modo',
detailScenario: 'Cena',
detailPlatform: 'Plataforma',
detailSurface: 'Superfície',
detailAuthor: 'Autor',
detailManifestId: 'ID do manifest',
detailTags: 'Tags',
detailPreviewCaption: 'Preview do manifest bundled-plugin.',
detailBucketLabel: { examples: 'Exemplo', 'image-templates': 'Template de imagem', 'video-templates': 'Template de vídeo', scenarios: 'Cena', 'design-systems': 'Design system', atoms: 'Atom' },
detailOpenInNewTabAria: 'Abrir em nova aba',
breadcrumbLabel: 'Trilha de navegação',
shareDialogClose: 'Fechar',
previewImageAlt: (title) => `Pré-visualização de ${title}`,
previewSummaryAria: (title) => `Abrir pré-visualização interativa de ${title}`,
previewIframeTitle: (title) => `Pré-visualização interativa de ${title}`,
},
it: {
hubLabel: 'Libreria plugin', hubHeading: (n) => `${n} pezzi componibili.`,
tileTemplates: 'Modelli', tileSkills: 'Skill', tileSystems: 'Sistemi', tileCraft: 'Artigianato',
browseTemplates: 'Esplora modelli', browseSkills: 'Esplora skill', browseSystems: 'Esplora sistemi', browseCraft: 'Esplora artigianato',
artifactKindLabel: 'Tipo di artefatto', sceneLabel: 'Scena', allChip: 'Tutti',
detailUseCta: 'Usa questo plugin →', detailFindOnGithub: 'Vedi su GitHub →',
detailClickForLivePreview: 'Clicca per anteprima live ↗', detailOpenInNewTab: 'Apri in nuova scheda ↗',
shareOpen: 'Condividi ↗', shareTitle: 'Condividi questo plugin',
shareLead: 'Copia il messaggio e apri la piattaforma su cui vuoi condividere.',
shareCopyText: 'Copia testo', shareCopyLink: 'Solo il link', shareJumpTo: 'Vai a:',
shareTemplate: ({ title, url }) => `🎨 Ho appena scoperto ${title} su @opendesignai — lalternativa open-source a Claude Design.\n✨ Local-first · BYOK · il tuo agente progetta.\n\n→ ${url}`,
hubLead: 'Open Design è costruito attorno a quattro tipi di plugin: Templates e Skill sono ciò che il tuo agent esegue; Systems e Craft tengono insieme brand e accessibilità. Scegli una sezione in cui scendere o salta a uno slug se sai già quale ti serve.',
tileTemplatesBlurb: 'Template visuali ed eseguibili — prototipi, slide, generatori di immagine e video, composizioni motion. Ogni voce porta un example.html: fai fork, cambia i dati, spedisci.',
tileSkillsBlurb: 'Skill di istruzione che lagent carica a metà task — copy, teoria del colore, direzione creativa, brainstorming. Pura prosa SKILL.md; il risultato dipende dallinput.',
tileSystemsBlurb: 'Design system ancorati al brand — palette, tipografia, motion, voice. Aggancia un progetto a un sistema e ogni output di plugin eredita la stessa identità.',
tileCraftBlurb: 'Regole di craft agnostiche al brand — accessibilità, RTL, easing motion, etica fotografica. Le skill fanno opt-in via `od.craft.requires`, e il plugin eredita automaticamente la rigorosità giusta.',
templatesLabel: 'Plugin · Template',
templatesHeading: (n) => `${n} template eseguibili.`,
templatesLead: 'Ogni template include una preview funzionante — la thumbnail del catalogo arriva diretta dal poster del manifest che lagent usa dentro il prodotto. Sfogliali tutti o salta a una delle sette classi di artefatto.',
skillsLabel: 'Plugin · Skill',
skillsHeading: (n) => `${n} skill di istruzione.`,
skillsLead: 'Skill che lagent carica durante un task — copy, teoria del colore, direzione creativa, brainstorming. Niente demo statica perché il risultato dipende dallinput; ogni pagina di dettaglio si legge come un brief: titolo, descrizione, trigger, attribuzione.',
systemsLabel: 'Plugin · Sistemi',
systemsHeading: (n) => `${n} design system.`,
systemsLead: 'Design system ancorati al brand che i plugin possono adottare via `od.craft.requires`. Ognuno con palette, tipografia, motion e voice; aggancia un progetto a un sistema e ogni output di plugin eredita la stessa identità.',
craftLabel: 'Plugin · Craft',
craftHeading: (n) => `${n} principi di craft.`,
craftLead: 'Regole di craft agnostiche al brand — accessibilità, RTL, easing motion, etica fotografica. Le skill fanno opt-in via `od.craft.requires`, e il plugin eredita la rigorosità giusta automaticamente.',
detailHomepage: 'Sito ↗',
detailMode: 'Modalità',
detailScenario: 'Scena',
detailPlatform: 'Piattaforma',
detailSurface: 'Superficie',
detailAuthor: 'Autore',
detailManifestId: 'ID manifest',
detailTags: 'Tag',
detailPreviewCaption: 'Preview dal manifest bundled-plugin.',
detailBucketLabel: { examples: 'Esempio', 'image-templates': 'Template immagine', 'video-templates': 'Template video', scenarios: 'Scena', 'design-systems': 'Design system', atoms: 'Atom' },
detailOpenInNewTabAria: 'Apri in una nuova scheda',
breadcrumbLabel: 'Percorso di navigazione',
shareDialogClose: 'Chiudi',
previewImageAlt: (title) => `Anteprima di ${title}`,
previewSummaryAria: (title) => `Apri anteprima interattiva di ${title}`,
previewIframeTitle: (title) => `Anteprima interattiva di ${title}`,
},
id: {
hubLabel: 'Pustaka plugin', hubHeading: (n) => `${n} potongan yang bisa digabungkan.`,
tileTemplates: 'Template', tileSkills: 'Skill', tileSystems: 'Sistem', tileCraft: 'Kerajinan',
browseTemplates: 'Jelajahi template', browseSkills: 'Jelajahi skill', browseSystems: 'Jelajahi sistem', browseCraft: 'Jelajahi kerajinan',
artifactKindLabel: 'Jenis artefak', sceneLabel: 'Adegan', allChip: 'Semua',
detailUseCta: 'Gunakan plugin ini →', detailFindOnGithub: 'Lihat di GitHub →',
detailClickForLivePreview: 'Klik untuk live preview ↗', detailOpenInNewTab: 'Buka di tab baru ↗',
shareOpen: 'Bagikan ↗', shareTitle: 'Bagikan plugin ini',
shareLead: 'Salin pesan di bawah, lalu buka platform yang ingin Anda gunakan dan tempel.',
shareCopyText: 'Salin teks', shareCopyLink: 'Salin tautan', shareJumpTo: 'Buka:',
shareTemplate: ({ title, url }) => `🎨 Baru nemu ${title} di @opendesignai — alternatif open-source untuk Claude Design.\n✨ Local-first · BYOK · agent kamu yang nge-desain.\n\n→ ${url}`,
hubLead: 'Open Design dibangun di sekitar empat jenis plugin: Templates dan Skills adalah yang dijalankan agent kamu; Systems dan Craft menjaga brand dan aksesibilitas. Pilih satu bagian untuk mendalami, atau lompat langsung ke slug kalau sudah tahu mau yang mana.',
tileTemplatesBlurb: 'Template visual dan dapat dijalankan — prototipe, slide, generator gambar dan video, komposisi motion. Setiap entri membawa example.html: fork, ganti data, kirim.',
tileSkillsBlurb: 'Skill instruksi yang dimuat agent di tengah tugas — copywriting, teori warna, arah kreatif, brainstorming. Murni prosa SKILL.md; hasil tergantung input kamu.',
tileSystemsBlurb: 'Design system yang berlabuh di brand — palet, tipografi, motion, voice. Kaitkan proyek ke system, dan setiap output plugin mewarisi identitas yang sama.',
tileCraftBlurb: 'Aturan craft yang agnostik brand — aksesibilitas, RTL, easing motion, etika fotografi. Skills opt-in lewat `od.craft.requires`, plugin otomatis mewarisi kekakuan yang sesuai.',
templatesLabel: 'Plugin · Template',
templatesHeading: (n) => `${n} template yang dapat dijalankan.`,
templatesLead: 'Setiap template memiliki preview yang berfungsi — thumbnail katalog langsung dari poster manifest yang dipakai agent di dalam produk. Telusuri semua atau lompat ke salah satu dari tujuh jenis artefak.',
skillsLabel: 'Plugin · Skill',
skillsHeading: (n) => `${n} skill instruksi.`,
skillsLead: 'Skill yang agent muat di tengah tugas — copywriting, teori warna, arah kreatif, brainstorming. Tidak ada demo statis karena hasil tergantung input; setiap halaman detail dibaca seperti brief: judul, deskripsi, trigger, atribusi.',
systemsLabel: 'Plugin · Sistem',
systemsHeading: (n) => `${n} design system.`,
systemsLead: 'Design system yang berlabuh di brand yang dapat diadopsi plugin lewat `od.craft.requires`. Masing-masing punya palet, tipografi, motion dan voice; kaitkan proyek ke system, semua output plugin mewarisi identitas yang sama.',
craftLabel: 'Plugin · Craft',
craftHeading: (n) => `${n} prinsip craft.`,
craftLead: 'Aturan craft agnostik brand — aksesibilitas, RTL, easing motion, etika fotografi. Skills opt-in via `od.craft.requires`, plugin otomatis mewarisi kekakuan yang sesuai.',
detailHomepage: 'Beranda ↗',
detailMode: 'Mode',
detailScenario: 'Adegan',
detailPlatform: 'Platform',
detailSurface: 'Permukaan',
detailAuthor: 'Penulis',
detailManifestId: 'ID manifest',
detailTags: 'Tag',
detailPreviewCaption: 'Preview dari manifest bundled-plugin.',
detailBucketLabel: { examples: 'Contoh', 'image-templates': 'Template gambar', 'video-templates': 'Template video', scenarios: 'Adegan', 'design-systems': 'Design system', atoms: 'Atom' },
detailOpenInNewTabAria: 'Buka di tab baru',
breadcrumbLabel: 'Navigasi breadcrumb',
shareDialogClose: 'Tutup',
previewImageAlt: (title) => `Pratinjau ${title}`,
previewSummaryAria: (title) => `Buka pratinjau interaktif ${title}`,
previewIframeTitle: (title) => `Pratinjau interaktif ${title}`,
},
pl: {
hubLabel: 'Biblioteka pluginów', hubHeading: (n) => `${n} komponowalnych elementów.`,
tileTemplates: 'Szablony', tileSkills: 'Umiejętności', tileSystems: 'Systemy', tileCraft: 'Rzemiosło',
browseTemplates: 'Przeglądaj szablony', browseSkills: 'Przeglądaj skille', browseSystems: 'Przeglądaj systemy', browseCraft: 'Przeglądaj rzemiosło',
artifactKindLabel: 'Typ artefaktu', sceneLabel: 'Scena', allChip: 'Wszystkie',
detailUseCta: 'Użyj tego pluginu →', detailFindOnGithub: 'Zobacz na GitHubie →',
detailClickForLivePreview: 'Kliknij, aby zobaczyć podgląd ↗', detailOpenInNewTab: 'Otwórz w nowej karcie ↗',
shareOpen: 'Udostępnij ↗', shareTitle: 'Udostępnij ten plugin',
shareLead: 'Skopiuj wiadomość poniżej, otwórz wybraną platformę i wklej.',
shareCopyText: 'Kopiuj tekst', shareCopyLink: 'Skopiuj link', shareJumpTo: 'Przejdź do:',
shareTemplate: ({ title, url }) => `🎨 Właśnie odkryłem ${title} na @opendesignai — open-sourceową alternatywę dla Claude Design.\n✨ Local-first · BYOK · twój agent projektuje.\n\n→ ${url}`,
hubLead: 'Open Design opiera się na czterech rodzajach wtyczek: Templates i Skills to to, co uruchamia twój agent; Systems i Craft pilnują marki i dostępności. Wybierz sekcję, by zejść głębiej, albo skocz prosto do sluga, jeśli już wiesz, czego chcesz.',
tileTemplatesBlurb: 'Wizualne, wykonywalne szablony — prototypy, slajdy, generatory obrazów i wideo, kompozycje motion. Każda pozycja ma example.html: forkujesz, podmieniasz dane, wysyłasz.',
tileSkillsBlurb: 'Wtyczki instrukcyjne, które agent wczytuje w trakcie zadania — copywriting, teoria koloru, kierunek kreatywny, burze mózgów. Czysty tekst SKILL.md; wynik zależy od twojego inputu.',
tileSystemsBlurb: 'Design systemy zakotwiczone w marce — paleta, typografia, motion, głos. Podepnij projekt do systemu, a każdy output wtyczki dziedziczy tę samą tożsamość.',
tileCraftBlurb: 'Reguły craftu niezależne od marki — dostępność, RTL, easing motion, etyka fotografii. Skills włączają się przez `od.craft.requires`, a wtyczka automatycznie dziedziczy odpowiednią surowość.',
templatesLabel: 'Wtyczki · Szablony',
templatesHeading: (n) => `${n} wykonywalnych szablonów.`,
templatesLead: 'Każdy szablon ma działający podgląd — miniatura w katalogu przychodzi prosto z postera manifestu, którego agent używa wewnątrz produktu. Przejrzyj wszystkie albo skocz do jednej z siedmiu klas artefaktu.',
skillsLabel: 'Wtyczki · Skille',
skillsHeading: (n) => `${n} skilli instrukcyjnych.`,
skillsLead: 'Skille, które agent wczytuje w trakcie zadania — copywriting, teoria koloru, kierunek kreatywny, burze mózgów. Bez statycznego demo, bo wynik zależy od inputu; każda strona szczegółu czyta się jak brief: tytuł, opis, triggery, atrybucja.',
systemsLabel: 'Wtyczki · Systemy',
systemsHeading: (n) => `${n} design systemów.`,
systemsLead: 'Zakotwiczone w marce design systemy, które wtyczki mogą przyjąć przez `od.craft.requires`. Każdy z własną paletą, typografią, motion i głosem; podepnij projekt do systemu, a każdy output wtyczki dziedziczy tę samą tożsamość.',
craftLabel: 'Wtyczki · Craft',
craftHeading: (n) => `${n} zasad craftu.`,
craftLead: 'Reguły craftu niezależne od marki — dostępność, RTL, easing motion, etyka fotografii. Skills włączają się przez `od.craft.requires`, a wtyczka automatycznie dziedziczy odpowiednią surowość.',
detailHomepage: 'Strona główna ↗',
detailMode: 'Tryb',
detailScenario: 'Scena',
detailPlatform: 'Platforma',
detailSurface: 'Powierzchnia',
detailAuthor: 'Autor',
detailManifestId: 'ID manifestu',
detailTags: 'Tagi',
detailPreviewCaption: 'Podgląd z manifestu bundled-plugin.',
detailBucketLabel: { examples: 'Przykład', 'image-templates': 'Szablon obrazu', 'video-templates': 'Szablon wideo', scenarios: 'Scena', 'design-systems': 'Design system', atoms: 'Atom' },
detailOpenInNewTabAria: 'Otwórz w nowej karcie',
breadcrumbLabel: 'Ścieżka nawigacyjna',
shareDialogClose: 'Zamknij',
previewImageAlt: (title) => `Podgląd ${title}`,
previewSummaryAria: (title) => `Otwórz interaktywny podgląd ${title}`,
previewIframeTitle: (title) => `Interaktywny podgląd ${title}`,
},
ar: {
hubLabel: 'مكتبة الإضافات', hubHeading: (n) => `${n} قطعة قابلة للتركيب.`,
tileTemplates: 'قوالب', tileSkills: 'مهارات', tileSystems: 'أنظمة', tileCraft: 'حِرَفية',
browseTemplates: 'تصفح القوالب', browseSkills: 'تصفح المهارات', browseSystems: 'تصفح الأنظمة', browseCraft: 'تصفح الحِرَفية',
artifactKindLabel: 'نوع المنتج', sceneLabel: 'مشهد', allChip: 'الكل',
detailUseCta: 'استخدم هذه الإضافة ←', detailFindOnGithub: 'اعرضها على GitHub ←',
detailClickForLivePreview: 'انقر للمعاينة الحية ↗', detailOpenInNewTab: 'افتح في علامة تبويب جديدة ↗',
shareOpen: 'مشاركة ↗', shareTitle: 'شارك هذه الإضافة',
shareLead: 'انسخ الرسالة أدناه، ثم انتقل إلى المنصة التي تريد المشاركة عليها والصقها.',
shareCopyText: 'انسخ النص', shareCopyLink: 'انسخ الرابط فقط', shareJumpTo: 'انتقل إلى:',
shareTemplate: ({ title, url }) => `🎨 اكتشفت للتو ${title} على @opendesignai — البديل مفتوح المصدر لـ Claude Design.\n✨ محلي أولًا · BYOK · وكيلك يصمّم.\n\n→ ${url}`,
hubLead: 'تم بناء Open Design حول أربعة أنواع من الإضافات: القوالب والمهارات هي ما يشغّله الـ agent؛ والأنظمة والحرفة تحافظان على الهوية وإمكانية الوصول. اختر قسما للتعمق، أو انتقل مباشرة إلى slug إذا كنت تعرف ما تريد.',
tileTemplatesBlurb: 'قوالب مرئية وقابلة للتشغيل — نماذج أولية، شرائح، مولّدات صور وفيديو، تركيبات حركة. كل مدخل يأتي مع example.html: انسخ، بدّل البيانات، اطلق.',
tileSkillsBlurb: 'مهارات إرشاد يحملها الـ agent أثناء المهمة — كتابة، نظرية الألوان، توجيه إبداعي، عصف ذهني. نص SKILL.md خالص؛ النتيجة تعتمد على مدخلاتك.',
tileSystemsBlurb: 'أنظمة تصميم مرتبطة بالهوية — لوحة ألوان، تيبوغرافيا، حركة، صوت. اربط مشروعا بنظام، فترث كل مخرجات الإضافات نفس الهوية.',
tileCraftBlurb: 'قواعد حرفة لا تعتمد على الهوية — إمكانية الوصول، RTL، انسيابية الحركة، أخلاقيات التصوير. تشترك المهارات عبر `od.craft.requires`، فترث الإضافة الصرامة المناسبة تلقائيا.',
templatesLabel: 'إضافات · قوالب',
templatesHeading: (n) => `${n} قالبا قابلا للتشغيل.`,
templatesLead: 'كل قالب يأتي مع معاينة شغّالة — صورة الكتالوج المصغّرة تأتي مباشرة من بوستر manifest الذي يستخدمه الـ agent داخل المنتج. تصفّح الجميع، أو انتقل إلى أحد الأنواع السبعة من المنتجات.',
skillsLabel: 'إضافات · مهارات',
skillsHeading: (n) => `${n} مهارة إرشاد.`,
skillsLead: 'مهارات يحملها الـ agent أثناء المهمة — كتابة، نظرية الألوان، توجيه إبداعي، عصف ذهني. لا توجد demo ثابتة لأن النتيجة تعتمد على المدخل؛ كل صفحة تفصيل تُقرأ كموجز: عنوان، وصف، محفّزات، إسناد.',
systemsLabel: 'إضافات · أنظمة',
systemsHeading: (n) => `${n} نظام تصميم.`,
systemsLead: 'أنظمة تصميم مرتبطة بالهوية يمكن للإضافات تبنّيها عبر `od.craft.requires`. لكل واحد لوحة، تيبوغرافيا، حركة وصوت خاصة؛ اربط مشروعا بنظام وكل مخرجات إضافة ترث نفس الهوية.',
craftLabel: 'إضافات · حرفة',
craftHeading: (n) => `${n} مبدأ حرفة.`,
craftLead: 'قواعد حرفة لا تعتمد على الهوية — إمكانية الوصول، RTL، انسيابية الحركة، أخلاقيات التصوير. المهارات تشترك عبر `od.craft.requires`، فترث الإضافة الصرامة المناسبة تلقائيا.',
detailHomepage: 'الصفحة الرئيسية ↗',
detailMode: 'الوضع',
detailScenario: 'المشهد',
detailPlatform: 'المنصة',
detailSurface: 'السطح',
detailAuthor: 'المؤلف',
detailManifestId: 'معرف Manifest',
detailTags: 'الوسوم',
detailPreviewCaption: 'معاينة من bundled-plugin manifest.',
detailBucketLabel: { examples: 'مثال', 'image-templates': 'قالب صور', 'video-templates': 'قالب فيديو', scenarios: 'مشهد', 'design-systems': 'نظام تصميم', atoms: 'Atom' },
detailOpenInNewTabAria: 'فتح في علامة تبويب جديدة',
breadcrumbLabel: 'مسار التنقل',
shareDialogClose: 'إغلاق',
previewImageAlt: (title) => `معاينة ${title}`,
previewSummaryAria: (title) => `فتح المعاينة التفاعلية لـ ${title}`,
previewIframeTitle: (title) => `المعاينة التفاعلية لـ ${title}`,
},
tr: {
hubLabel: 'Eklenti kütüphanesi', hubHeading: (n) => `${n} birleştirilebilir parça.`,
tileTemplates: 'Şablonlar', tileSkills: 'Yetenekler', tileSystems: 'Sistemler', tileCraft: 'Zanaat',
browseTemplates: 'Şablonları gözat', browseSkills: 'Yetenekleri gözat', browseSystems: 'Sistemleri gözat', browseCraft: 'Zanaatı gözat',
artifactKindLabel: ıktı türü', sceneLabel: 'Sahne', allChip: 'Tümü',
detailUseCta: 'Bu eklentiyi kullan →', detailFindOnGithub: 'GitHubda görüntüle →',
detailClickForLivePreview: 'Canlı önizleme için tıkla ↗', detailOpenInNewTab: 'Yeni sekmede aç ↗',
shareOpen: 'Paylaş ↗', shareTitle: 'Bu eklentiyi paylaş',
shareLead: 'Aşağıdaki mesajı kopyala, dilediğin platformu açıp yapıştır.',
shareCopyText: 'Metni kopyala', shareCopyLink: 'Sadece linki kopyala', shareJumpTo: 'Şuraya git:',
shareTemplate: ({ title, url }) => `🎨 Yeni keşfettim: ${title} (@opendesignai) — Claude Designa açık kaynaklı alternatif.\n✨ Local-first · BYOK · ajanın tasarlıyor.\n\n→ ${url}`,
hubLead: 'Open Design dört eklenti türü etrafında inşa edilmiştir: Templates ve Skills agentın çalıştırdığı, Systems ve Craft ise marka ve erişilebilirliği koruyan parçalar. Bir bölüme dal ya da hangi slugu istediğini biliyorsan doğrudan oraya zıpla.',
tileTemplatesBlurb: 'Görsel ve çalıştırılabilir şablonlar — prototipler, slaytlar, görsel ve video üreticileri, motion kompozisyonları. Her giriş example.html ile gelir: fork, veri değiştir, gönder.',
tileSkillsBlurb: 'Agentın görev sırasında yüklediği yönerge skillleri — metin yazımı, renk teorisi, kreatif yönlendirme, beyin fırtınası. Saf SKILL.md metni; sonuç inputuna göre değişir.',
tileSystemsBlurb: 'Markaya bağlanmış tasarım sistemleri — palet, tipografi, motion, ses. Bir projeyi bir sisteme bağla, tüm eklenti çıktıları aynı kimliği miras alsın.',
tileCraftBlurb: 'Markadan bağımsız craft kuralları — erişilebilirlik, RTL, motion easing, fotoğraf etiği. Skills `od.craft.requires` ile opt-in eder, eklenti uygun katılığı otomatik miras alır.',
templatesLabel: 'Eklentiler · Şablonlar',
templatesHeading: (n) => `${n} çalıştırılabilir şablon.`,
templatesLead: 'Her şablon çalışan bir önizleme ile gelir — katalog satırının küçük resmi doğrudan agentın ürün içinde kullandığı manifest posterından alınır. Hepsine bak ya da yedi artefakt türünden birine zıpla.',
skillsLabel: 'Eklentiler · Skilller',
skillsHeading: (n) => `${n} yönerge skilli.`,
skillsLead: 'Agentın görev sırasında yüklediği skilller — metin yazımı, renk teorisi, kreatif yönlendirme, beyin fırtınası. Sonuç inputa bağlı olduğu için statik demo yok; her detay sayfası bir brief gibi okunur: başlık, açıklama, tetikler, atıf.',
systemsLabel: 'Eklentiler · Sistemler',
systemsHeading: (n) => `${n} tasarım sistemi.`,
systemsLead: 'Eklentilerin `od.craft.requires` ile benimseyebildiği markaya bağlı tasarım sistemleri. Her biri kendi paleti, tipografisi, motionı ve sesi ile gelir; projeni bir sisteme bağla, tüm eklenti çıktıları aynı kimliği miras alır.',
craftLabel: 'Eklentiler · Craft',
craftHeading: (n) => `${n} craft prensibi.`,
craftLead: 'Markadan bağımsız craft kuralları — erişilebilirlik, RTL, motion easing, fotoğraf etiği. Skills `od.craft.requires` ile opt-in eder, eklenti uygun katılığı otomatik miras alır.',
detailHomepage: 'Anasayfa ↗',
detailMode: 'Mod',
detailScenario: 'Sahne',
detailPlatform: 'Platform',
detailSurface: 'Yüzey',
detailAuthor: 'Yazar',
detailManifestId: 'Manifest ID',
detailTags: 'Etiketler',
detailPreviewCaption: 'bundled-plugin manifestten önizleme.',
detailBucketLabel: { examples: 'Örnek', 'image-templates': 'Görsel şablon', 'video-templates': 'Video şablon', scenarios: 'Sahne', 'design-systems': 'Tasarım sistemi', atoms: 'Atom' },
detailOpenInNewTabAria: 'Yeni sekmede aç',
breadcrumbLabel: 'İçerik haritası',
shareDialogClose: 'Kapat',
previewImageAlt: (title) => `${title} önizlemesi`,
previewSummaryAria: (title) => `${title} için etkileşimli önizlemeyi aç`,
previewIframeTitle: (title) => `${title} etkileşimli önizleme`,
},
uk: {
hubLabel: 'Бібліотека плагінів', hubHeading: (n) => `${n} компонованих елементів.`,
tileTemplates: 'Шаблони', tileSkills: 'Навички', tileSystems: 'Системи', tileCraft: 'Ремесло',
browseTemplates: 'Переглянути шаблони', browseSkills: 'Переглянути навички', browseSystems: 'Переглянути системи', browseCraft: 'Переглянути ремесло',
artifactKindLabel: 'Тип артефакту', sceneLabel: 'Сцена', allChip: 'Усі',
detailUseCta: 'Використати цей плагін →', detailFindOnGithub: 'Дивитись на GitHub →',
detailClickForLivePreview: 'Клікніть для живого перегляду ↗', detailOpenInNewTab: 'Відкрити в новій вкладці ↗',
shareOpen: 'Поділитись ↗', shareTitle: 'Поділитись цим плагіном',
shareLead: 'Скопіюйте повідомлення нижче, потім перейдіть на платформу й вставте.',
shareCopyText: 'Копіювати текст', shareCopyLink: 'Тільки посилання', shareJumpTo: 'Перейти:',
shareTemplate: ({ title, url }) => `🎨 Щойно знайшов ${title} на @opendesignai — open-source альтернативу Claude Design.\n✨ Local-first · BYOK · ваш агент робить дизайн.\n\n→ ${url}`,
hubLead: 'Open Design побудовано навколо чотирьох видів плагінів: Templates і Skills — те, що виконує твій agent; Systems і Craft утримують бренд і доступність. Обери розділ для занурення або одразу перейди по slug, якщо вже знаєш, що потрібно.',
tileTemplatesBlurb: 'Візуальні, виконувані шаблони — прототипи, слайди, генератори зображень і відео, motion-композиції. Кожен запис іде з example.html: форкай, міняй дані, відправляй.',
tileSkillsBlurb: 'Інструкційні навички, які agent підвантажує під час задачі — копірайтинг, теорія кольору, креативне керівництво, брейншторм. Чистий текст SKILL.md; результат залежить від твого input.',
tileSystemsBlurb: 'Прив’язані до бренду дизайн-системи — палітра, типографіка, motion, тон. Прив’яжи проєкт до системи, і будь-який вивід плагіна успадковує ту саму ідентичність.',
tileCraftBlurb: 'Бренд-агностичні craft-правила — доступність, RTL, motion-easing, етика фотографії. Навички opt-in через `od.craft.requires`, і плагін автоматично успадковує потрібну строгість.',
templatesLabel: 'Плагіни · Шаблони',
templatesHeading: (n) => `${n} виконуваних шаблонів.`,
templatesLead: 'Кожен шаблон має робочий попередній перегляд — мініатюра в каталозі береться прямо з manifest poster, який agent використовує всередині продукту. Перегляньте всі або стрибніть до однієї з семи категорій артефактів.',
skillsLabel: 'Плагіни · Навички',
skillsHeading: (n) => `${n} інструкційних навичок.`,
skillsLead: 'Навички, які agent підвантажує під час задачі — копірайтинг, теорія кольору, креативне керівництво, брейншторм. Статичної demo немає, бо результат залежить від input; кожна сторінка деталей читається як brief: заголовок, опис, тригери, авторство.',
systemsLabel: 'Плагіни · Системи',
systemsHeading: (n) => `${n} дизайн-систем.`,
systemsLead: 'Прив’язані до бренду дизайн-системи, які плагіни можуть прийняти через `od.craft.requires`. Кожна з власною палітрою, типографікою, motion і тоном; прив’яжи проєкт до системи — будь-який вивід плагіна успадковує ту саму ідентичність.',
craftLabel: 'Плагіни · Craft',
craftHeading: (n) => `${n} принципів craft.`,
craftLead: 'Бренд-агностичні craft-правила — доступність, RTL, motion-easing, етика фотографії. Навички opt-in через `od.craft.requires`, плагін автоматично успадковує потрібну строгість.',
detailHomepage: 'Головна ↗',
detailMode: 'Режим',
detailScenario: 'Сцена',
detailPlatform: 'Платформа',
detailSurface: 'Поверхня',
detailAuthor: 'Автор',
detailManifestId: 'ID маніфесту',
detailTags: 'Теги',
detailPreviewCaption: 'Прев’ю з bundled-plugin маніфесту.',
detailBucketLabel: { examples: 'Приклад', 'image-templates': 'Шаблон зображення', 'video-templates': 'Шаблон відео', scenarios: 'Сцена', 'design-systems': 'Дизайн-система', atoms: 'Atom' },
detailOpenInNewTabAria: 'Відкрити в новій вкладці',
breadcrumbLabel: 'Навігаційна стежка',
shareDialogClose: 'Закрити',
previewImageAlt: (title) => `Прев’ю ${title}`,
previewSummaryAria: (title) => `Відкрити інтерактивне прев’ю ${title}`,
previewIframeTitle: (title) => `Інтерактивне прев’ю ${title}`,
},
vi: {
hubLabel: 'Thư viện plugin', hubHeading: (n) => `${n} thành phần có thể ghép nối.`,
tileTemplates: 'Mẫu', tileSkills: 'Kỹ năng', tileSystems: 'Hệ thống', tileCraft: 'Thủ công',
browseTemplates: 'Xem các mẫu', browseSkills: 'Xem kỹ năng', browseSystems: 'Xem hệ thống', browseCraft: 'Xem thủ công',
artifactKindLabel: 'Loại sản phẩm', sceneLabel: 'Cảnh', allChip: 'Tất cả',
detailUseCta: 'Dùng plugin này →', detailFindOnGithub: 'Xem trên GitHub →',
detailClickForLivePreview: 'Nhấn để xem preview trực tiếp ↗', detailOpenInNewTab: 'Mở trong tab mới ↗',
shareOpen: 'Chia sẻ ↗', shareTitle: 'Chia sẻ plugin này',
shareLead: 'Sao chép nội dung dưới đây, rồi mở nền tảng bạn muốn chia sẻ và dán vào.',
shareCopyText: 'Sao chép', shareCopyLink: 'Chỉ sao chép link', shareJumpTo: 'Mở:',
shareTemplate: ({ title, url }) => `🎨 Vừa khám phá ${title} trên @opendesignai — giải pháp mã nguồn mở thay thế Claude Design.\n✨ Ưu tiên local · BYOK · agent của bạn thiết kế.\n\n→ ${url}`,
hubLead: 'Open Design xoay quanh bốn loại plugin: Templates và Skills là thứ agent của bạn chạy; Systems và Craft giữ thương hiệu và tính tiếp cận. Chọn một mục để đào sâu, hoặc nhảy thẳng tới một slug nếu bạn đã biết cần gì.',
tileTemplatesBlurb: 'Templates trực quan và chạy được — nguyên mẫu, slide, bộ sinh ảnh và video, bố cục motion. Mỗi mục có example.html: fork, đổi dữ liệu, ship ngay.',
tileSkillsBlurb: 'Các skill chỉ dẫn mà agent nạp giữa tác vụ — copy, lý thuyết màu, chỉ đạo sáng tạo, brainstorm. Văn xuôi SKILL.md thuần; kết quả tuỳ input của bạn.',
tileSystemsBlurb: 'Design system bám thương hiệu — bảng màu, kiểu chữ, motion, giọng nói. Gán một dự án vào một system và mọi đầu ra plugin sẽ kế thừa cùng một danh tính.',
tileCraftBlurb: 'Các quy tắc craft không phụ thuộc thương hiệu — tiếp cận, RTL, easing motion, đạo đức nhiếp ảnh. Skills opt-in qua `od.craft.requires`, plugin tự kế thừa độ chặt phù hợp.',
templatesLabel: 'Plugin · Templates',
templatesHeading: (n) => `${n} templates chạy được.`,
templatesLead: 'Mỗi template đều có preview chạy được — thumbnail trong catalog lấy trực tiếp từ manifest poster mà agent dùng trong sản phẩm. Lướt hết, hoặc nhảy tới một trong bảy loại artifact.',
skillsLabel: 'Plugin · Skills',
skillsHeading: (n) => `${n} skill chỉ dẫn.`,
skillsLead: 'Skills agent nạp giữa tác vụ — copy, lý thuyết màu, chỉ đạo sáng tạo, brainstorm. Không có demo tĩnh vì kết quả phụ thuộc input; mỗi trang chi tiết đọc như một brief: tiêu đề, mô tả, trigger, ghi nguồn.',
systemsLabel: 'Plugin · Systems',
systemsHeading: (n) => `${n} design system.`,
systemsLead: 'Design system bám thương hiệu mà plugin có thể chấp nhận qua `od.craft.requires`. Mỗi system có bảng màu, kiểu chữ, motion và voice riêng; gán dự án vào system, mọi đầu ra plugin kế thừa cùng danh tính.',
craftLabel: 'Plugin · Craft',
craftHeading: (n) => `${n} nguyên tắc craft.`,
craftLead: 'Quy tắc craft không phụ thuộc thương hiệu — tiếp cận, RTL, easing motion, đạo đức nhiếp ảnh. Skills opt-in qua `od.craft.requires`, plugin tự kế thừa độ chặt phù hợp.',
detailHomepage: 'Trang chủ ↗',
detailMode: 'Chế độ',
detailScenario: 'Cảnh',
detailPlatform: 'Nền tảng',
detailSurface: 'Bề mặt',
detailAuthor: 'Tác giả',
detailManifestId: 'ID manifest',
detailTags: 'Thẻ',
detailPreviewCaption: 'Preview từ manifest bundled-plugin.',
detailBucketLabel: { examples: 'Ví dụ', 'image-templates': 'Template ảnh', 'video-templates': 'Template video', scenarios: 'Cảnh', 'design-systems': 'Design system', atoms: 'Atom' },
detailOpenInNewTabAria: 'Mở trong tab mới',
breadcrumbLabel: 'Đường dẫn',
shareDialogClose: 'Đóng',
previewImageAlt: (title) => `Xem trước ${title}`,
previewSummaryAria: (title) => `Mở xem trước tương tác của ${title}`,
previewIframeTitle: (title) => `Xem trước tương tác của ${title}`,
},
nl: {
hubLabel: 'Plugin-bibliotheek', hubHeading: (n) => `${n} combineerbare onderdelen.`,
tileTemplates: 'Templates', tileSkills: 'Skills', tileSystems: 'Systemen', tileCraft: 'Vakmanschap',
browseTemplates: 'Bekijk templates', browseSkills: 'Bekijk skills', browseSystems: 'Bekijk systemen', browseCraft: 'Bekijk vakmanschap',
artifactKindLabel: 'Type artefact', sceneLabel: 'Scène', allChip: 'Alle',
detailUseCta: 'Gebruik deze plugin →', detailFindOnGithub: 'Bekijk op GitHub →',
detailClickForLivePreview: 'Klik voor live preview ↗', detailOpenInNewTab: 'Open in nieuw tabblad ↗',
shareOpen: 'Delen ↗', shareTitle: 'Deel deze plugin',
shareLead: 'Kopieer het bericht hieronder en plak het op het platform van jouw keuze.',
shareCopyText: 'Tekst kopiëren', shareCopyLink: 'Alleen de link', shareJumpTo: 'Ga naar:',
shareTemplate: ({ title, url }) => `🎨 Net ontdekt: ${title} op @opendesignai — het open-source alternatief voor Claude Design.\n✨ Local-first · BYOK · jouw agent ontwerpt.\n\n→ ${url}`,
hubLead: 'Open Design is gebouwd rond vier soorten plug-ins: Templates en Skills zijn wat je agent draait; Systems en Craft houden merk en toegankelijkheid op orde. Kies een sectie om dieper in te duiken, of spring direct naar een slug als je al weet wat je wilt.',
tileTemplatesBlurb: 'Visuele, draaiende templates — prototypes, slides, beeld- en videogeneratoren, motion-composities. Elke entry levert een example.html: fork, wissel data, ship.',
tileSkillsBlurb: 'Instructie-skills die de agent halverwege een taak laadt — copy, kleurtheorie, creatieve regie, brainstorm. Pure SKILL.md-tekst; het resultaat hangt af van je input.',
tileSystemsBlurb: 'Merk-verankerde designsystemen — palet, typografie, motion, voice. Koppel een project aan een systeem en elke plug-in-output erft dezelfde identiteit.',
tileCraftBlurb: 'Merkagnostische craft-regels — toegankelijkheid, RTL, motion-easing, fotografie-ethiek. Skills opten in via `od.craft.requires`, zodat een plug-in automatisch de juiste striktheid erft.',
templatesLabel: 'Plug-ins · Templates',
templatesHeading: (n) => `${n} draaiende templates.`,
templatesLead: 'Elke template levert een werkende preview — de thumbnail in de catalogus komt direct van de manifest-poster die de agent in het product gebruikt. Bekijk ze allemaal of spring naar een van de zeven artefactsoorten.',
skillsLabel: 'Plug-ins · Skills',
skillsHeading: (n) => `${n} instructie-skills.`,
skillsLead: 'Skills die de agent tijdens een taak laadt — copy, kleurtheorie, creatieve regie, brainstorm. Geen statische demo omdat de uitkomst van je input afhangt; elke detailpagina leest als een brief: titel, beschrijving, triggers, attributie.',
systemsLabel: 'Plug-ins · Systemen',
systemsHeading: (n) => `${n} designsystemen.`,
systemsLead: 'Merk-verankerde designsystemen die plug-ins kunnen overnemen via `od.craft.requires`. Elk levert eigen palet, typografie, motion en voice; koppel een project aan een systeem en elke plug-in-output erft dezelfde identiteit.',
craftLabel: 'Plug-ins · Vakmanschap',
craftHeading: (n) => `${n} craft-principes.`,
craftLead: 'Merkagnostische craft-regels — toegankelijkheid, RTL, motion-easing, fotografie-ethiek. Skills opten in via `od.craft.requires`, zodat een plug-in automatisch de juiste striktheid erft.',
detailHomepage: 'Homepage ↗',
detailMode: 'Modus',
detailScenario: 'Scène',
detailPlatform: 'Platform',
detailSurface: 'Oppervlak',
detailAuthor: 'Auteur',
detailManifestId: 'Manifest-ID',
detailTags: 'Tags',
detailPreviewCaption: 'Preview uit het bundled-plugin-manifest.',
detailBucketLabel: { examples: 'Voorbeeld', 'image-templates': 'Beeld-template', 'video-templates': 'Video-template', scenarios: 'Scène', 'design-systems': 'Designsysteem', atoms: 'Atom' },
detailOpenInNewTabAria: 'Openen in nieuw tabblad',
breadcrumbLabel: 'Kruimelpad',
shareDialogClose: 'Sluiten',
previewImageAlt: (title) => `Voorvertoning van ${title}`,
previewSummaryAria: (title) => `Interactieve voorvertoning van ${title} openen`,
previewIframeTitle: (title) => `Interactieve voorvertoning van ${title}`,
},
};
/**
* Resolve a complete `PluginsCopy` object for a given locale, merging
* locale overrides on top of the English baseline. Missing keys fall
* back to English so a partially-translated locale still renders
* sensibly.
*/
export function getPluginsCopy(locale: LandingLocaleCode): PluginsCopy {
if (locale === DEFAULT_LOCALE) return en;
const partial = overrides[locale];
if (!partial) return en;
return {
...en,
...partial,
category: { ...en.category, ...(partial.category ?? {}) },
subcategory: { ...en.subcategory, ...(partial.subcategory ?? {}) },
detailBucketLabel: { ...en.detailBucketLabel, ...(partial.detailBucketLabel ?? {}) },
};
}