Skills Plugins MCP Prompt Model 博客 我的中心

i18n-translate

Complete and maintain frontend i18n translations for this project. Covers finding missing translation keys, detecting untranslated entries, and adding translations for all supported locales (en, zh, zh-TW, fr, ja, ru, vi). Use for any task involving frontend locale files, missing translation keys, untranslated UI text, `t(...)` keys, `useTranslation()`, static i18n keys, button/label/ toast/dialog/placeholder/validation copy, or adding/fixing even a single i18n key. Use when review findings mention missing i18n, when new UI text needs translation, or when the user asks to add translations, fix i18n, or complete missing translations. Always load and follow this skill before translating, adding locale keys, or editing frontend i18n files.

DeepseekModel 官方收录技能 质量 优秀 · 90 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=quantumnous-new-api-agents-skills-i18n-translate-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name i18n-translate description Complete and maintain frontend i18n translations for this project. Covers finding missing translation keys, detecting untranslated entries, and adding translations for all supported locales (en, zh, zh-TW, fr, ja, ru, vi). Use for any task involving frontend locale files, missing translation keys, untranslated UI text, `t(...)` keys, `useTranslation()`, static i18n keys, button/label/ toast/dialog/placeholder/validation copy, or adding/fixing even a single i18n key. Use when review findings mention missing i18n, when new UI text needs translation, or when the user asks to add translations, fix i18n, or complete missing translations. Always load and follow this skill before translating, adding locale keys, or editing frontend i18n files. Frontend i18n Translation Workflow Mandatory Preflight Read this entire SKILL.md before any frontend i18n work, including one-key fixes. Before editing locale files, confirm the source text comes from a t(...) key, en.json , existing UI copy, or an explicitly requested new UI string. Use the user conversation only to understand the task target. Do not copy conversation text, review wording, or task descriptions directly into locale values. Before translating each key, re-think the intended UI copy from the code and locale context instead of treating the surrounding chat as the translation source. Hard Constraint: Locale Writes Go Through the Script You MUST NOT edit web/src/i18n/locales/*.json directly with text-editing tools (StrReplace, Write, search-and-replace, manual JSON edits, etc.). This applies even to a single key. ALL locale writes MUST go through the add-missing-keys.mjs script, followed by bun run i18n:sync . The script is the only sanctioned way to add or change locale values. Why this is mandatory, not optional: Hand-editing reliably drops one or more of the seven locales ( en , zh , zh-TW , fr , ja , ru , vi ), leaving keys missing in some languages. Hand-editing breaks the required alphabetical key order and introduces JSON syntax errors (trailing commas, mismatched quotes). The script writes all seven files atomically with consistent sorting, so the locale set stays in sync by construction. The script does not do the translation for you. You still must reason out each locale's copy and populate the script's newKeys object; the script only handles insertion, sorting, and writing. Do not skip the script just because the thinking happens regardless. Scope Checklist Before editing files, treat the task as covered by this skill if it involves: i18n , translation, locale files, language packs, missing keys, or untranslated text t('...') , useTranslation() , static-keys.ts , or locales/*.json UI copy in buttons, labels, toasts, dialogs, placeholders, validation messages, descriptions, or table/empty states A review finding about missing i18n keys Do not skip this workflow because the fix is "just one key". Overview Locale files: web/src/i18n/locales/{en,zh,zh-TW,fr,ja,ru,vi}.json Format: flat JSON under "translation" key, keys are English source strings Base locale: en.json (most keys), fallback: zh (Chinese) Sync script: bun run i18n:sync (from web/ ) All t() calls must have corresponding keys in every locale file Small Fix Path For a single known missing key (still script-only, no direct JSON edits): Confirm the exact key at the call site and verify it is absent from all locale files. Add the key via add-missing-keys.mjs , populating its newKeys object for every supported locale: en , zh , zh-TW , fr , ja , ru , vi . Even one key goes through the script; do not hand-edit the JSON. The script preserves the flat "translation" object and keeps keys alphabetically sorted automatically. Run a targeted search for the key in code and locale files. Run bun run i18n:sync to normalize file order. This step is mandatory, not optional. Workflow Step 1: Run sync and read report cd web && bun run i18n: sync Read web/src/i18n/locales/_reports/_sync-report.json to see per-locale status (missingCount, extrasCount, untranslatedCount). Step 2: Find missing keys (used in code but not in locale files) Create and run web/scripts/find-missing-keys.mjs : import fs from 'node:fs/promises' import path from 'node:path' const LOCALES_DIR = path. resolve ( 'src/i18n/locales' ) const SRC_DIR = path. resolve ( 'src' ) const en = JSON . parse ( await fs. readFile (path. join ( LOCALES_DIR , 'en.json' ), 'utf8' )) const enKeys = new Set ( Object . keys (en. translation )) const tCallRegex = /\bt\(\s*['"`]([^'"`\n]+?)['"`]\s*[,)]/g const tCallMultilineRegex = /\bt\(\s*['"`]([^'"`]+?)['"`]\s*\)/g async function walkDir ( dir ) { const files = [] const entries = await fs. readdir (dir, { withFileTypes : true }) for ( const entry of entries) { const fullPath = path. join (dir, entry. name ) if (entry. isDirectory ()) { if ([ 'node_modules' , '.git' , 'locales' , '_reports' , '_extras' ]. includes (entry. name )) continue files. push (...( await walkDir (fullPath))) } else if ( /\.(tsx?|jsx?)$/ . test (entry. name )) { files. push (fullPath) } } return files } const files = await walkDir ( SRC_DIR ) const missingKeys = new Map () for ( const file of files) { const content = await fs. readFile (file, 'utf8' ) const relPath = path. relative ( SRC_DIR , file) for ( const regex of [tCallRegex, tCallMultilineRegex]) { regex. lastIndex = 0 let match while ((match = regex. exec (content)) !== null ) { const key = match[ 1 ] if (key. startsWith ( '{{' ) || key. includes ( '${' )) continue if (!enKeys. has (key)) { if (!missingKeys. has (key)) missingKeys. set (key, []) missingKeys. get (key). push (relPath) } } } } if (missingKeys. size === 0 ) { console . log ( 'All t() keys found in en.json!' ) } else { console . log ( `Found ${missingKeys.size} missing keys:\n` ) for ( const [key, files] of [...missingKeys. entries ()]. sort ( ( [a], [b] ) => a. localeCompare (b))) { console . log ( ` " ${key} "` ) for ( const f of [... new Set (files)]) console . log ( ` -> ${f} ` ) } } Step 3: Find untranslated entries (value equals English) Create and run web/scripts/find-untranslated.mjs : import fs from 'node:fs/promises' import path from 'node:path' const LOCALES_DIR = path. resolve ( 'src/i18n/locales' ) const en = JSON . parse ( await fs. readFile (path. join ( LOCALES_DIR , 'en.json' ), 'utf8' )) const enTrans = en. translation // Brand names, URLs, technical terms — skip these const skipPatterns = [ /^https?:\/\// , /^smtp\./ , /^socks5:/ , /^name@/ , /^noreply@/ , /^org-/ , /^price_/ , /^whsec_/ , /^edit_this$/ , /^my-status$/ , /^_copy$/ , /^gpt-/ , /^checkout\./ , /^footer\./ , /^\[?\{/ , /^"default/ , /^\/status\// , /^\/your\// , /^example\.com/ , /^AZURE_/ , /^AccessKey/ , /^OAuth/ , /^Client / , /^Webhook URL/ , /^API URL$/ , /^Well-Known/ , /^Worker URL$/ , /^Uptime Kuma/ , /^New API/ , /^Baidu V2$/ , /^Zhipu V4$/ , /^Quota:$/ , ] const brandNames = new Set ([ 'AIGC2D' , 'Anthropic' , 'API2GPT' , 'Claude' , 'Cloudflare' , 'Cohere' , 'DeepSeek' , 'Discord' , 'DoubaoVideo' , 'FastGPT' , 'Gemini' , 'GitHub' , 'Jimeng' , 'JustSong' , 'LingYiWanWu' , 'LinuxDO' , 'Midjourney' , 'MidjourneyPlus' , 'MiniMax' , 'Mistral' , 'MokaAI' , 'Moonshot' , 'NewAPI' , 'OhMyGPT' , 'Ollama' , 'OpenAI' , 'OpenAIMax' , 'OpenRouter' , 'Passkey' , 'Perplexity' , 'QuantumNous' , 'Replicate' , 'SiliconFlow' , 'Stripe' , 'Submodel' , 'SunoAPI' , 'Telegram' , 'Tencent' , 'Vertex AI' , 'VolcEngine' , 'WeChat' , 'Xinference' , 'Xunfei' , 'AI Proxy' , 'One API' , ]) const locales = [ 'fr' , 'ja' , 'ru' , 'zh' , 'zh-TW' , 'vi' ] for ( const locale of locales) { const locFile = JSON . parse ( await fs. readFile (path. join ( LOCALES_DIR , ` ${locale} .json` ), 'utf8' )) const locTrans = locFile. translation const untranslated = {} for ( const [key, enVal] of Object . entries (enTrans)) { const locVal = locTrans[key] if (locVal === undefined || locVal !== enVal) continue if (brandNames. has (key)) continue if (skipPatterns. some ( p => p. test (key))) continue if ( typeof enVal === 'string' && enVal. length < 4 ) continue if ( /[a-zA-Z]{3,}/ . test ( String (enVal))) untranslated[key] = enVal } const count = Object . keys (untranslated). length if (count > 0 ) { console . log ( `\n=== ${locale} ( ${count} untranslated) ===` ) for ( const [k, v] of Object . entries (untranslated)) console . log ( ` ${ JSON .stringify(k)} : ${ JSON .stringify(v)} ` ) } else { console . log ( `\n=== ${locale} : all translated ===` ) } } Step 4: Add translations This script is the ONLY sanctioned way to write locale values. You MUST NOT bypass it by hand-filling the JSON files. Create web/scripts/add-missing-keys.mjs with this exact structure: import fs from 'node:fs/promises' import path from 'node:path' const LOCALES_DIR = path. resolve ( 'src/i18n/locales' ) function stableStringify ( obj ) { return JSON . stringify (obj, null , 2 ) + '\n' } const newKeys = { en : { /* "key": "English value" */ }, zh : { /* "key": "中文翻译" */ }, 'zh-TW' : { /* "key": "繁體中文翻譯" */ }, fr : { /* "key": "Traduction française" */ }, ja : { /* "key": "日本語翻訳" */ }, ru : { /* "key": "Русский перевод" */ }, vi : { /* "key": "Bản dịch tiếng Việt" */ }, } async function main ( ) { let totalAdded = 0 for ( const [locale, trans] of Object . entries (newKeys)) { const filePath = path. join ( LOCALES_DIR , ` ${locale} .json` ) const json = JSON . parse ( await fs. readFile (filePath, 'utf8' )) let count = 0 for ( const [key, value] of Object . entries (trans)) { if (! Object . prototype . hasOwnProperty . call (json. translation , key)) { json. translation [key] = value count++ } else if (json. translation [key] !== value) { json. translation [key] = value count++ } } if (count > 0 ) { json. translation = Object . fromEntries ( Object . entries (json. translation ). sort ( ( [a], [b] ) => a. localeCompare (b)) ) await fs. writeFile (filePath, stableStringify (json), 'utf8' ) } console . log ( ` ${locale} : ${count} translations applied` ) totalAdded += count } console . log ( `\nTotal: ${totalAdded} translations applied` ) } main (). catch ( ( err ) => { console . error (err); process. exitCode = 1 }) Populate the newKeys object with actual translations for each locale. Step 5: Verify and clean up cd web node scripts/add-missing-keys.mjs # apply translations node scripts/find-missing-keys.mjs # verify: should say "All t() keys found" bun run i18n: sync # normalize file order Delete temporary scripts after completion. Translation Guidelines Source Text Rules Reconsider every key's UI meaning before translating: component location, user action, placeholder variables, button/label/toast/dialog/validation context, and whether the copy is a noun, command, status, or full sentence. Prefer the English key or en value as the source text. Use the call site only to clarify meaning, tone, and constraints. Do not copy chat messages, review comments, issue descriptions, or task wording as translation text. If the source text is unclear, inspect the code and locale files first. Ask the user for exact source copy only when the intended UI text remains ambiguous. Length and Layout Awareness Consider whether translated text may overflow the UI before choosing final wording, especially for buttons, table headers, menu items, labels, toasts, dialog titles, tabs, badges, and empty states. For languages that often expand relative to English, especially French, Russian, and Vietnamese, prefer natural but compact wording. Do not sacrifice meaning just to shorten text. When the call site has limited space, choose the shortest clear translation that preserves the UI intent. For interpolated variables, counts, model names, provider names, quotas, and dates, consider the longest realistic rendered text, not only the translation string itself. | Language | Code | Notes |
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

验证码 --

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。