Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "jta",
|
||||
"description": "AI-powered JSON i18n translation with agentic reflection mechanism for high-quality multilingual content",
|
||||
"version": "0.0.0-2025.11.28",
|
||||
"author": {
|
||||
"name": "Kanner",
|
||||
"email": "kanner.chen@gmail.com"
|
||||
},
|
||||
"skills": [
|
||||
"./skills/jta"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# jta
|
||||
|
||||
AI-powered JSON i18n translation with agentic reflection mechanism for high-quality multilingual content
|
||||
68
plugin.lock.json
Normal file
68
plugin.lock.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:hikanner/agent-skills:jta",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "e3599a7cce656dda7fd28e8f59b0907f7cb4d28d",
|
||||
"treeHash": "c8147e26ab3a535e1fae08180ae1b77999925a422b81f0b84e1285b70caf3c0b",
|
||||
"generatedAt": "2025-11-28T10:17:28.097760Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "jta",
|
||||
"description": "AI-powered JSON i18n translation with agentic reflection mechanism for high-quality multilingual content"
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "8e71b1958cd04a4d0ca0745ea5bf1cad1656fd98bcfe65b9dd0b7bbaff524be2"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "2c04fdbcefb8f633f20a9c045c781f0410ded148852c19e8e71a8367a99d05fd"
|
||||
},
|
||||
{
|
||||
"path": "skills/jta/.gitignore",
|
||||
"sha256": "9e2f5ca1ef531f8af6b18624a8e6b5efb075fafc8c08dd8e7d4c0dccab5a38de"
|
||||
},
|
||||
{
|
||||
"path": "skills/jta/SKILL.md",
|
||||
"sha256": "966c16971c049c678d6e5da4183076ddbbe135650cfb4b095224f1b8329f8d51"
|
||||
},
|
||||
{
|
||||
"path": "skills/jta/LICENSE.txt",
|
||||
"sha256": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
|
||||
},
|
||||
{
|
||||
"path": "skills/jta/examples/basic-translation.md",
|
||||
"sha256": "93a78d5cceb3da4fdcfcbd7d4e3df459bc92811472ce3c238f0f541eec9fab2f"
|
||||
},
|
||||
{
|
||||
"path": "skills/jta/examples/ci-cd-integration.md",
|
||||
"sha256": "4edfd907f786e50cb2f922a1cb1c6df39dfebff5ce1ef5438faa7fba8010742c"
|
||||
},
|
||||
{
|
||||
"path": "skills/jta/examples/incremental-mode.md",
|
||||
"sha256": "a7310c057a2582e03991f425827b2754cbde4771c4f301c0deec2c61c793fc8c"
|
||||
},
|
||||
{
|
||||
"path": "skills/jta/scripts/install.sh",
|
||||
"sha256": "3bb057bd0d179732f01332cabc6b8b9cd1216af32b9f3c7b1464f24ed95951ad"
|
||||
}
|
||||
],
|
||||
"dirSha256": "c8147e26ab3a535e1fae08180ae1b77999925a422b81f0b84e1285b70caf3c0b"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
35
skills/jta/.gitignore
vendored
Normal file
35
skills/jta/.gitignore
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# macOS
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Testing
|
||||
test/
|
||||
*.test.json
|
||||
.jta/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
201
skills/jta/LICENSE.txt
Normal file
201
skills/jta/LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
357
skills/jta/SKILL.md
Normal file
357
skills/jta/SKILL.md
Normal file
@@ -0,0 +1,357 @@
|
||||
---
|
||||
name: jta
|
||||
description: Translate JSON i18n files to multiple languages with AI-powered quality optimization. Use when user mentions translating JSON, i18n files, internationalization, locale files, or needs to convert language files to other languages.
|
||||
version: 1.0.0
|
||||
license: Complete terms in LICENSE.txt
|
||||
allowed-tools: Read, Write, Bash, Glob
|
||||
---
|
||||
|
||||
# Jta Translation
|
||||
|
||||
AI-powered JSON internationalization file translator with Agentic reflection mechanism.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- User asks to translate JSON i18n/locale files
|
||||
- User mentions "internationalization", "i18n", "l10n", or "locale"
|
||||
- User wants to add new languages to their project
|
||||
- User needs to update existing translations
|
||||
- User mentions specific languages like "translate to Chinese/Japanese/Korean"
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
1. **Agentic Translation**: AI translates, evaluates, and improves its own work (3x API calls per batch)
|
||||
2. **Smart Terminology**: Automatically detects and maintains consistent terms (brand names, technical terms)
|
||||
3. **Format Protection**: Preserves `{variables}`, `{{placeholders}}`, HTML tags, URLs, Markdown
|
||||
4. **Incremental Mode**: Only translates new/changed content (saves 80-90% API cost on updates)
|
||||
5. **27 Languages**: Including RTL languages (Arabic, Hebrew, Persian, Urdu)
|
||||
|
||||
## Instructions
|
||||
|
||||
### Step 1: Check if jta is installed
|
||||
|
||||
```bash
|
||||
# Check if jta exists
|
||||
if ! command -v jta &> /dev/null; then
|
||||
echo "jta not found, will install"
|
||||
fi
|
||||
```
|
||||
|
||||
### Step 2: Install jta if needed
|
||||
|
||||
```bash
|
||||
# Detect OS and install jta
|
||||
OS="$(uname -s)"
|
||||
ARCH="$(uname -m)"
|
||||
|
||||
if [[ "$OS" == "Darwin"* ]]; then
|
||||
# macOS - try Homebrew first
|
||||
if command -v brew &> /dev/null; then
|
||||
brew tap hikanner/jta
|
||||
brew install jta
|
||||
else
|
||||
# Download binary
|
||||
if [[ "$ARCH" == "arm64" ]]; then
|
||||
curl -L https://github.com/hikanner/jta/releases/latest/download/jta-darwin-arm64 -o jta
|
||||
else
|
||||
curl -L https://github.com/hikanner/jta/releases/latest/download/jta-darwin-amd64 -o jta
|
||||
fi
|
||||
chmod +x jta
|
||||
sudo mv jta /usr/local/bin/
|
||||
fi
|
||||
elif [[ "$OS" == "Linux"* ]]; then
|
||||
# Linux
|
||||
curl -L https://github.com/hikanner/jta/releases/latest/download/jta-linux-amd64 -o jta
|
||||
chmod +x jta
|
||||
sudo mv jta /usr/local/bin/
|
||||
fi
|
||||
|
||||
# Verify installation
|
||||
jta --version
|
||||
```
|
||||
|
||||
### Step 3: Check for API key and set provider
|
||||
|
||||
Jta requires an AI provider API key. Check in this order and set the provider flag:
|
||||
|
||||
```bash
|
||||
# Detect API key and set provider flag
|
||||
if [[ -n "$ANTHROPIC_API_KEY" ]]; then
|
||||
echo "✓ Anthropic API key found"
|
||||
PROVIDER_FLAG="--provider anthropic"
|
||||
elif [[ -n "$GEMINI_API_KEY" ]]; then
|
||||
echo "✓ Gemini API key found"
|
||||
PROVIDER_FLAG="--provider gemini"
|
||||
elif [[ -n "$OPENAI_API_KEY" ]]; then
|
||||
echo "✓ OpenAI API key found"
|
||||
PROVIDER_FLAG="" # OpenAI is default, no flag needed
|
||||
else
|
||||
echo "✗ No API key found. Please set one of:"
|
||||
echo " export OPENAI_API_KEY=sk-..."
|
||||
echo " export ANTHROPIC_API_KEY=sk-ant-..."
|
||||
echo " export GEMINI_API_KEY=..."
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**Important:** Save the `PROVIDER_FLAG` value to use in translation commands.
|
||||
|
||||
### Step 4: Identify source file
|
||||
|
||||
```bash
|
||||
# Find JSON files in common i18n/locale directories
|
||||
find . -type f -name "*.json" \
|
||||
\( -path "*/locales/*" -o \
|
||||
-path "*/locale/*" -o \
|
||||
-path "*/i18n/*" -o \
|
||||
-path "*/lang/*" -o \
|
||||
-path "*/translations/*" \) \
|
||||
| head -20
|
||||
```
|
||||
|
||||
Ask user to confirm which file to translate if multiple found.
|
||||
|
||||
### Step 5: Determine translation requirements
|
||||
|
||||
Ask user (if not specified in their request):
|
||||
- Target languages (e.g., "zh,ja,ko")
|
||||
- Whether to use incremental mode (recommended for updates)
|
||||
- Output location preference
|
||||
|
||||
### Step 6: Execute translation
|
||||
|
||||
**Always use `$PROVIDER_FLAG` from Step 3** to ensure the correct AI provider is used:
|
||||
|
||||
```bash
|
||||
# Basic translation with detected provider
|
||||
jta <source-file> --to <target-langs> $PROVIDER_FLAG
|
||||
|
||||
# Examples:
|
||||
# Single language
|
||||
jta en.json --to zh $PROVIDER_FLAG
|
||||
|
||||
# Multiple languages
|
||||
jta en.json --to zh,ja,ko $PROVIDER_FLAG
|
||||
|
||||
# Incremental mode (for updates)
|
||||
jta en.json --to zh --incremental $PROVIDER_FLAG
|
||||
|
||||
# With custom output
|
||||
jta en.json --to zh --output ./locales/zh.json $PROVIDER_FLAG
|
||||
|
||||
# Non-interactive mode (for multiple languages)
|
||||
jta en.json --to zh,ja,ko,es,fr -y $PROVIDER_FLAG
|
||||
|
||||
# Override with specific model for quality
|
||||
jta en.json --to zh --provider anthropic --model claude-sonnet-4-5
|
||||
|
||||
# Translate specific keys only
|
||||
jta en.json --to zh --keys "settings.*,user.*" $PROVIDER_FLAG
|
||||
|
||||
# Exclude certain keys
|
||||
jta en.json --to zh --exclude-keys "admin.*,internal.*" $PROVIDER_FLAG
|
||||
```
|
||||
|
||||
### Step 7: Verify results
|
||||
|
||||
After translation completes:
|
||||
|
||||
```bash
|
||||
# Check output files exist
|
||||
ls -lh <output-files>
|
||||
|
||||
# Validate JSON structure
|
||||
for file in <output-files>; do
|
||||
if jq empty "$file" 2>/dev/null; then
|
||||
echo "✓ $file is valid JSON"
|
||||
else
|
||||
echo "✗ $file has invalid JSON"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
### Step 8: Report to user
|
||||
|
||||
Show the user:
|
||||
- Translation statistics (total items, success rate, API calls, duration)
|
||||
- Location of output files
|
||||
- Any errors or warnings
|
||||
- Cost implications if significant (e.g., "Used 15 API calls, estimated $0.30")
|
||||
|
||||
## Terminology Management
|
||||
|
||||
Jta automatically creates a `.jta/` directory to store terminology:
|
||||
|
||||
```
|
||||
.jta/
|
||||
├── terminology.json # Source language terms (preserve + consistent)
|
||||
├── terminology.zh.json # Chinese translations
|
||||
├── terminology.ja.json # Japanese translations
|
||||
└── terminology.ko.json # Korean translations
|
||||
```
|
||||
|
||||
**terminology.json** structure:
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"sourceLanguage": "en",
|
||||
"preserveTerms": ["API", "OAuth", "GitHub"],
|
||||
"consistentTerms": ["credits", "workspace", "prompt"]
|
||||
}
|
||||
```
|
||||
|
||||
Users can manually edit these files for custom terminology.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Note:** Always include `$PROVIDER_FLAG` (from Step 3) in your commands.
|
||||
|
||||
### Pattern 1: First-time translation
|
||||
```bash
|
||||
# User: "Translate my en.json to Chinese and Japanese"
|
||||
jta locales/en.json --to zh,ja -y $PROVIDER_FLAG
|
||||
```
|
||||
|
||||
### Pattern 2: Update existing translations
|
||||
```bash
|
||||
# User: "I added new keys to en.json, update the translations"
|
||||
jta locales/en.json --to zh,ja --incremental -y $PROVIDER_FLAG
|
||||
```
|
||||
|
||||
### Pattern 3: Translate specific sections
|
||||
```bash
|
||||
# User: "Only translate the settings and user sections"
|
||||
jta en.json --to zh --keys "settings.**,user.**" $PROVIDER_FLAG
|
||||
```
|
||||
|
||||
### Pattern 4: High-quality translation
|
||||
```bash
|
||||
# User: "Use the best model for highest quality"
|
||||
jta en.json --to zh --provider anthropic --model claude-sonnet-4-5
|
||||
```
|
||||
|
||||
### Pattern 5: RTL languages
|
||||
```bash
|
||||
# User: "Translate to Arabic and Hebrew"
|
||||
jta en.json --to ar,he -y $PROVIDER_FLAG
|
||||
# Jta automatically handles bidirectional text markers
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error: "jta: command not found"
|
||||
- Run the installation script from Step 2
|
||||
- Verify with `jta --version`
|
||||
|
||||
### Error: "API key not set"
|
||||
Prompt user:
|
||||
```
|
||||
Jta requires an AI provider API key. Please set one of:
|
||||
|
||||
For OpenAI (recommended):
|
||||
export OPENAI_API_KEY=sk-...
|
||||
Get key at: https://platform.openai.com/api-keys
|
||||
|
||||
For Anthropic:
|
||||
export ANTHROPIC_API_KEY=sk-ant-...
|
||||
Get key at: https://console.anthropic.com/
|
||||
|
||||
For Google Gemini:
|
||||
export GEMINI_API_KEY=...
|
||||
Get key at: https://aistudio.google.com/app/apikey
|
||||
```
|
||||
|
||||
### Error: "Rate limit exceeded"
|
||||
```bash
|
||||
# Reduce batch size and concurrency
|
||||
jta en.json --to zh --batch-size 10 --concurrency 1
|
||||
```
|
||||
|
||||
### Error: "Invalid JSON"
|
||||
```bash
|
||||
# Validate source file
|
||||
jq . source.json
|
||||
```
|
||||
|
||||
### Error: Translation quality issues
|
||||
1. Try a better model:
|
||||
```bash
|
||||
jta en.json --to zh --provider anthropic --model claude-sonnet-4-5
|
||||
```
|
||||
|
||||
2. Check terminology files in `.jta/` and edit if needed
|
||||
|
||||
3. Use verbose mode to debug:
|
||||
```bash
|
||||
jta en.json --to zh --verbose
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- **Small files (<100 keys)**: Use default settings
|
||||
- **Large files (>500 keys)**: Use `--batch-size 10 --concurrency 2`
|
||||
- **Frequent updates**: Always use `--incremental` to save cost
|
||||
- **Quality priority**: Use `--provider anthropic --model claude-sonnet-4-5`
|
||||
- **Speed priority**: Use `--provider openai --model gpt-3.5-turbo` (if available)
|
||||
- **Cost priority**: Use incremental mode + larger batch sizes
|
||||
|
||||
## Supported Languages
|
||||
|
||||
27 languages with full support:
|
||||
|
||||
**Left-to-Right (LTR):**
|
||||
- European: en, es, fr, de, it, pt, ru, nl, pl, tr
|
||||
- Asian: zh, zh-TW, ja, ko, th, vi, id, ms, hi, bn, si, ne, my
|
||||
|
||||
**Right-to-Left (RTL):**
|
||||
- Middle Eastern: ar, fa, he, ur
|
||||
|
||||
View all supported languages:
|
||||
```bash
|
||||
jta --list-languages
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
Jta produces:
|
||||
1. **Translated JSON files**: Same structure as source, with translations
|
||||
2. **Statistics**: Printed to console
|
||||
3. **Terminology files**: In `.jta/` directory for consistency
|
||||
|
||||
Always inform the user of:
|
||||
- Number of items translated
|
||||
- Success/failure count
|
||||
- Output file locations
|
||||
- Any errors or warnings
|
||||
- API usage and estimated cost (if significant)
|
||||
|
||||
## Advanced Options
|
||||
|
||||
**Note:** Remember to include `$PROVIDER_FLAG` in your commands.
|
||||
|
||||
```bash
|
||||
# Skip terminology detection (use existing)
|
||||
jta en.json --to zh --skip-terminology $PROVIDER_FLAG
|
||||
|
||||
# Disable terminology management completely
|
||||
jta en.json --to zh --no-terminology $PROVIDER_FLAG
|
||||
|
||||
# Re-detect terminology (when source language changes)
|
||||
jta en.json --to zh --redetect-terms $PROVIDER_FLAG
|
||||
|
||||
# Custom terminology directory (for shared terms)
|
||||
jta en.json --to zh --terminology-dir ../shared-terms/ $PROVIDER_FLAG
|
||||
|
||||
# Specify source language explicitly
|
||||
jta myfile.json --source-lang en --to zh $PROVIDER_FLAG
|
||||
|
||||
# Custom batch size and concurrency
|
||||
jta en.json --to zh --batch-size 20 --concurrency 3 $PROVIDER_FLAG
|
||||
|
||||
# Verbose output for debugging
|
||||
jta en.json --to zh --verbose $PROVIDER_FLAG
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
See [examples/](examples/) directory for detailed, step-by-step use cases.
|
||||
265
skills/jta/examples/basic-translation.md
Normal file
265
skills/jta/examples/basic-translation.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# Example: Basic Translation
|
||||
|
||||
This example demonstrates the most common use case: translating a JSON i18n file to multiple languages.
|
||||
|
||||
## Scenario
|
||||
|
||||
User has `locales/en.json` containing English translations and wants to add Chinese, Japanese, and Korean support.
|
||||
|
||||
## User Request
|
||||
|
||||
> "Translate my en.json to Chinese, Japanese, and Korean"
|
||||
|
||||
## Claude's Workflow
|
||||
|
||||
### Step 1: Understand the Request
|
||||
|
||||
Claude recognizes:
|
||||
- **Task**: Translation
|
||||
- **Source file**: en.json (implied to be in locales/)
|
||||
- **Target languages**: Chinese (zh), Japanese (ja), Korean (ko)
|
||||
- **Mode**: First-time translation (full, not incremental)
|
||||
|
||||
### Step 2: Locate the Source File
|
||||
|
||||
```bash
|
||||
# Find JSON files in locale directories
|
||||
find . -type f -name "en.json" \( -path "*/locales/*" -o -path "*/locale/*" -o -path "*/i18n/*" \)
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
./locales/en.json
|
||||
```
|
||||
|
||||
### Step 3: Check Environment
|
||||
|
||||
```bash
|
||||
# Verify jta is installed
|
||||
jta --version
|
||||
```
|
||||
|
||||
If not installed:
|
||||
```bash
|
||||
# Install via Homebrew (macOS)
|
||||
brew tap hikanner/jta && brew install jta
|
||||
```
|
||||
|
||||
Check API key:
|
||||
```bash
|
||||
# Check if API key exists
|
||||
if [[ -n "$OPENAI_API_KEY" ]]; then
|
||||
echo "✓ API key found"
|
||||
fi
|
||||
```
|
||||
|
||||
### Step 4: Preview Source File
|
||||
|
||||
```bash
|
||||
# Show file structure
|
||||
jq '.' locales/en.json | head -20
|
||||
```
|
||||
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"name": "My App",
|
||||
"welcome": "Welcome to {appName}!"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"language": "Language"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Execute Translation
|
||||
|
||||
```bash
|
||||
# Translate to Chinese, Japanese, and Korean
|
||||
jta locales/en.json --to zh,ja,ko -y
|
||||
```
|
||||
|
||||
**What happens:**
|
||||
1. **Terminology Detection**: Jta analyzes content and detects important terms
|
||||
2. **Batch Processing**: Splits into batches (default 20 keys per batch)
|
||||
3. **Translation**: Sends each batch to AI provider
|
||||
4. **Agentic Reflection**: AI evaluates and improves translations
|
||||
5. **Output**: Creates zh.json, ja.json, ko.json
|
||||
|
||||
### Step 6: Monitor Progress
|
||||
|
||||
Console output:
|
||||
```
|
||||
📄 Loading source file...
|
||||
✓ Source file loaded (100 keys)
|
||||
|
||||
📚 Loading terminology...
|
||||
🔍 Detecting terminology...
|
||||
✓ Detected 8 terms (3 preserve, 5 consistent)
|
||||
|
||||
🤖 Translating to Chinese (zh)...
|
||||
Processing ━━━━━━━━━━━━━━━━━━━━ 100% (100/100)
|
||||
✓ Chinese translation completed
|
||||
|
||||
🤖 Translating to Japanese (ja)...
|
||||
Processing ━━━━━━━━━━━━━━━━━━━━ 100% (100/100)
|
||||
✓ Japanese translation completed
|
||||
|
||||
🤖 Translating to Korean (ko)...
|
||||
Processing ━━━━━━━━━━━━━━━━━━━━ 100% (100/100)
|
||||
✓ Korean translation completed
|
||||
|
||||
💾 Saving translations...
|
||||
✓ Saved to locales/zh.json
|
||||
✓ Saved to locales/ja.json
|
||||
✓ Saved to locales/ko.json
|
||||
```
|
||||
|
||||
### Step 7: Verify Results
|
||||
|
||||
```bash
|
||||
# Check created files
|
||||
ls -lh locales/*.json
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
-rw-r--r-- 1 user staff 2.3K en.json
|
||||
-rw-r--r-- 1 user staff 2.8K zh.json
|
||||
-rw-r--r-- 1 user staff 3.1K ja.json
|
||||
-rw-r--r-- 1 user staff 2.9K ko.json
|
||||
```
|
||||
|
||||
Validate JSON structure:
|
||||
```bash
|
||||
for file in locales/{zh,ja,ko}.json; do
|
||||
if jq empty "$file" 2>/dev/null; then
|
||||
echo "✓ $file is valid JSON"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
### Step 8: Show Statistics
|
||||
|
||||
```
|
||||
📊 Translation Statistics
|
||||
|
||||
Chinese (zh):
|
||||
Total items: 100
|
||||
Success: 100
|
||||
Failed: 0
|
||||
Duration: 45s
|
||||
API calls: 15 (5 translate + 5 reflect + 5 improve)
|
||||
|
||||
Japanese (ja):
|
||||
Total items: 100
|
||||
Success: 100
|
||||
Failed: 0
|
||||
Duration: 48s
|
||||
API calls: 15
|
||||
|
||||
Korean (ko):
|
||||
Total items: 100
|
||||
Success: 100
|
||||
Failed: 0
|
||||
Duration: 43s
|
||||
API calls: 15
|
||||
|
||||
Total Duration: 2m 16s
|
||||
Total API calls: 45
|
||||
Estimated cost: ~$0.90 (using GPT-4o)
|
||||
|
||||
Terminology saved to .jta/ directory for future consistency.
|
||||
```
|
||||
|
||||
## Claude's Response to User
|
||||
|
||||
```
|
||||
✅ Translation completed successfully!
|
||||
|
||||
I've translated your en.json to Chinese, Japanese, and Korean.
|
||||
|
||||
**Files created:**
|
||||
- `locales/zh.json` (Chinese Simplified)
|
||||
- `locales/ja.json` (Japanese)
|
||||
- `locales/ko.json` (Korean)
|
||||
|
||||
**Statistics:**
|
||||
- Total items: 100 per language
|
||||
- Success rate: 100%
|
||||
- Duration: 2 minutes 16 seconds
|
||||
- API calls: 45 total (15 per language with Agentic reflection)
|
||||
- Estimated cost: ~$0.90
|
||||
|
||||
**Terminology management:**
|
||||
Jta detected 8 important terms and saved them to `.jta/` directory:
|
||||
- Preserve terms (never translate): API, OAuth, JSON
|
||||
- Consistent terms (translate uniformly): credits, workspace, settings, profile, template
|
||||
|
||||
All placeholders ({appName}), HTML tags, and URLs have been preserved in the translations.
|
||||
|
||||
Would you like me to show you a sample of the translations or make any adjustments?
|
||||
```
|
||||
|
||||
## Sample Translations
|
||||
|
||||
### English (source)
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "Welcome to {appName}!",
|
||||
"description": "Manage your <b>workspace</b> settings"
|
||||
},
|
||||
"user": {
|
||||
"credits": "You have {count} credits remaining"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Chinese (zh.json)
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "欢迎来到 {appName}!",
|
||||
"description": "管理您的<b>工作空间</b>设置"
|
||||
},
|
||||
"user": {
|
||||
"credits": "您还有 {count} 积分"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Japanese (ja.json)
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "{appName}へようこそ!",
|
||||
"description": "<b>ワークスペース</b>の設定を管理"
|
||||
},
|
||||
"user": {
|
||||
"credits": "残り {count} クレジットがあります"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Korean (ko.json)
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "{appName}에 오신 것을 환영합니다!",
|
||||
"description": "<b>워크스페이스</b> 설정 관리"
|
||||
},
|
||||
"user": {
|
||||
"credits": "{count}개의 크레딧이 남아 있습니다"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- All placeholders (`{appName}`, `{count}`) preserved
|
||||
- HTML tags (`<b>`) preserved
|
||||
- Terminology consistency maintained ("workspace" → "工作空间", "ワークスペース", "워크스페이스")
|
||||
- Agentic reflection ensured natural, fluent translations
|
||||
446
skills/jta/examples/ci-cd-integration.md
Normal file
446
skills/jta/examples/ci-cd-integration.md
Normal file
@@ -0,0 +1,446 @@
|
||||
# Example: CI/CD Integration
|
||||
|
||||
This example demonstrates how to automatically translate i18n files in a CI/CD pipeline whenever the source file changes.
|
||||
|
||||
## Scenario
|
||||
|
||||
Team maintains a multilingual web application. When developers update `en.json`, the CI/CD pipeline should automatically:
|
||||
1. Detect the change
|
||||
2. Translate to all target languages
|
||||
3. Commit the translations back to the repository
|
||||
|
||||
## User Request
|
||||
|
||||
> "Set up automatic translation in our GitHub Actions when en.json changes"
|
||||
|
||||
## Claude's Workflow
|
||||
|
||||
### Step 1: Understand Requirements
|
||||
|
||||
Claude recognizes:
|
||||
- **Platform**: GitHub Actions (CI/CD)
|
||||
- **Trigger**: Changes to en.json
|
||||
- **Target languages**: Multiple (need to confirm with user)
|
||||
- **Mode**: Incremental (to save costs)
|
||||
|
||||
### Step 2: Confirm Configuration
|
||||
|
||||
Claude asks:
|
||||
```
|
||||
To set up automatic translation, I need to know:
|
||||
1. What languages do you want to translate to?
|
||||
2. Where is your source file? (e.g., locales/en.json)
|
||||
3. Do you have an OPENAI_API_KEY secret set in GitHub?
|
||||
```
|
||||
|
||||
User responds:
|
||||
> "Translate to Chinese, Japanese, Korean, Spanish, and French. Source is `locales/en.json`. Yes, we have OPENAI_API_KEY in GitHub secrets."
|
||||
|
||||
### Step 3: Create GitHub Actions Workflow
|
||||
|
||||
```bash
|
||||
# Create workflow directory if it doesn't exist
|
||||
mkdir -p .github/workflows
|
||||
```
|
||||
|
||||
Create workflow file:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/translate-i18n.yml
|
||||
name: Auto-translate i18n files
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
paths:
|
||||
- 'locales/en.json'
|
||||
|
||||
jobs:
|
||||
translate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Full history for proper git operations
|
||||
|
||||
- name: Install Jta
|
||||
run: |
|
||||
curl -L https://github.com/hikanner/jta/releases/latest/download/jta-linux-amd64 -o jta
|
||||
chmod +x jta
|
||||
sudo mv jta /usr/local/bin/
|
||||
jta --version
|
||||
|
||||
- name: Translate to all languages
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
run: |
|
||||
# Use incremental mode to only translate changes
|
||||
# Non-interactive mode (-y) for CI/CD
|
||||
jta locales/en.json --to zh,ja,ko,es,fr --incremental -y
|
||||
|
||||
- name: Check for translation changes
|
||||
id: check_changes
|
||||
run: |
|
||||
# Check if any translation files were modified
|
||||
if [[ -n $(git status -s locales/*.json) ]]; then
|
||||
echo "changes=true" >> $GITHUB_OUTPUT
|
||||
echo "Translation files were updated"
|
||||
else
|
||||
echo "changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No translation changes"
|
||||
fi
|
||||
|
||||
- name: Commit and push translations
|
||||
if: steps.check_changes.outputs.changes == 'true'
|
||||
run: |
|
||||
git config user.name "Translation Bot"
|
||||
git config user.email "bot@example.com"
|
||||
git add locales/*.json
|
||||
git add .jta/ # Include terminology updates
|
||||
git commit -m "chore: auto-translate i18n files
|
||||
|
||||
- Updated translations for Chinese, Japanese, Korean, Spanish, French
|
||||
- Triggered by changes to en.json
|
||||
- Translated using Jta with incremental mode
|
||||
|
||||
🤖 Generated automatically by GitHub Actions"
|
||||
git push
|
||||
|
||||
- name: Comment on commit (optional)
|
||||
if: steps.check_changes.outputs.changes == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.repos.createCommitComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
commit_sha: context.sha,
|
||||
body: '✅ Translations updated automatically by Jta'
|
||||
})
|
||||
```
|
||||
|
||||
### Step 4: Set Up GitHub Secret
|
||||
|
||||
Create instructions for the user:
|
||||
|
||||
```bash
|
||||
# In GitHub repository settings:
|
||||
# 1. Go to Settings → Secrets and variables → Actions
|
||||
# 2. Click "New repository secret"
|
||||
# 3. Name: OPENAI_API_KEY
|
||||
# 4. Value: your OpenAI API key (sk-...)
|
||||
# 5. Click "Add secret"
|
||||
```
|
||||
|
||||
### Step 5: Create Pre-commit Hook (Optional)
|
||||
|
||||
For local development, create a pre-commit hook:
|
||||
|
||||
```bash
|
||||
# .git/hooks/pre-commit
|
||||
#!/bin/bash
|
||||
|
||||
# Check if en.json was modified
|
||||
if git diff --cached --name-only | grep -q "locales/en.json"; then
|
||||
echo "🔍 en.json modified, checking translations..."
|
||||
|
||||
# Check if API key exists
|
||||
if [[ -z "$OPENAI_API_KEY" ]]; then
|
||||
echo "⚠️ Warning: OPENAI_API_KEY not set. Translations will be updated in CI."
|
||||
else
|
||||
echo "🤖 Running incremental translation..."
|
||||
jta locales/en.json --to zh,ja,ko,es,fr --incremental -y
|
||||
|
||||
# Stage updated translations
|
||||
git add locales/*.json .jta/
|
||||
echo "✅ Translations updated and staged"
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
```bash
|
||||
chmod +x .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
## Claude's Response to User
|
||||
|
||||
```
|
||||
✅ CI/CD auto-translation setup complete!
|
||||
|
||||
I've created a GitHub Actions workflow that will automatically translate your i18n files.
|
||||
|
||||
**What I created:**
|
||||
1. `.github/workflows/translate-i18n.yml` - GitHub Actions workflow
|
||||
2. Instructions for setting up the API key secret
|
||||
|
||||
**How it works:**
|
||||
1. When you push changes to `locales/en.json` (on main or develop branches)
|
||||
2. GitHub Actions automatically:
|
||||
- Installs Jta
|
||||
- Translates to Chinese, Japanese, Korean, Spanish, French
|
||||
- Uses incremental mode (only translates new/changed keys)
|
||||
- Commits translations back to the repository
|
||||
|
||||
**Configuration:**
|
||||
- Target languages: zh, ja, ko, es, fr
|
||||
- Mode: Incremental (saves ~90% API cost on updates)
|
||||
- Trigger: Changes to locales/en.json on main/develop
|
||||
- API key: Uses OPENAI_API_KEY from GitHub secrets
|
||||
|
||||
**Next steps:**
|
||||
1. Ensure `OPENAI_API_KEY` is set in your GitHub repository secrets
|
||||
2. Commit and push the workflow file
|
||||
3. Test by making a change to `locales/en.json`
|
||||
|
||||
**Optional enhancement:**
|
||||
I can also create a pre-commit hook for local development, so translations
|
||||
run automatically before you commit. Would you like that?
|
||||
|
||||
**Cost estimation:**
|
||||
- First run (full translation): ~$1.50 for 100 keys × 5 languages
|
||||
- Subsequent runs (incremental): ~$0.15-0.30 for typical updates
|
||||
- The incremental mode will save significant costs over time
|
||||
```
|
||||
|
||||
## Workflow Visualization
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Dev as Developer
|
||||
participant Git as Git Repository
|
||||
participant GHA as GitHub Actions
|
||||
participant Jta as Jta
|
||||
participant AI as AI Provider
|
||||
|
||||
Dev->>Git: Push changes to en.json
|
||||
Git->>GHA: Trigger workflow
|
||||
GHA->>GHA: Checkout repository
|
||||
GHA->>GHA: Install Jta
|
||||
GHA->>Jta: Run translation (incremental)
|
||||
Jta->>AI: Translate changed keys
|
||||
AI-->>Jta: Return translations
|
||||
Jta->>Jta: Merge with existing translations
|
||||
Jta-->>GHA: Translation complete
|
||||
GHA->>Git: Commit translated files
|
||||
Git-->>Dev: Translations available
|
||||
```
|
||||
|
||||
## Testing the Workflow
|
||||
|
||||
### Test 1: Add New Keys
|
||||
|
||||
```bash
|
||||
# Add new keys to en.json
|
||||
vim locales/en.json
|
||||
```
|
||||
|
||||
Add:
|
||||
```json
|
||||
{
|
||||
"new": {
|
||||
"feature": "New Feature",
|
||||
"description": "This is a new feature"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Commit and push:
|
||||
```bash
|
||||
git add locales/en.json
|
||||
git commit -m "feat: add new feature translations"
|
||||
git push
|
||||
```
|
||||
|
||||
**Expected result:**
|
||||
- GitHub Actions triggers
|
||||
- Translates 2 new keys to 5 languages (10 translations total)
|
||||
- Commits translations back
|
||||
- Total time: ~30 seconds
|
||||
|
||||
### Test 2: Modify Existing Keys
|
||||
|
||||
```bash
|
||||
# Modify existing translation
|
||||
vim locales/en.json
|
||||
```
|
||||
|
||||
Change:
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "Welcome to our amazing platform!"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Commit and push:
|
||||
```bash
|
||||
git add locales/en.json
|
||||
git commit -m "fix: improve welcome message"
|
||||
git push
|
||||
```
|
||||
|
||||
**Expected result:**
|
||||
- GitHub Actions triggers
|
||||
- Updates 1 modified key in 5 languages
|
||||
- Preserves all other translations
|
||||
- Total time: ~15 seconds
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Multi-Environment Setup
|
||||
|
||||
```yaml
|
||||
name: Auto-translate i18n files
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
paths:
|
||||
- 'locales/en.json'
|
||||
|
||||
jobs:
|
||||
translate:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
environment: [staging, production]
|
||||
|
||||
steps:
|
||||
# ... (installation steps)
|
||||
|
||||
- name: Translate
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
run: |
|
||||
if [[ "${{ matrix.environment }}" == "production" ]]; then
|
||||
# Use highest quality for production
|
||||
jta locales/en.json --to zh,ja,ko,es,fr \
|
||||
--provider anthropic \
|
||||
--model claude-sonnet-4-5 \
|
||||
--incremental -y
|
||||
else
|
||||
# Use faster/cheaper for staging
|
||||
jta locales/en.json --to zh,ja,ko,es,fr \
|
||||
--incremental -y
|
||||
fi
|
||||
```
|
||||
|
||||
### With Approval Step
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
translate:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: translation-approval
|
||||
# Requires manual approval before running
|
||||
|
||||
steps:
|
||||
# ... (translation steps)
|
||||
```
|
||||
|
||||
### With Slack Notifications
|
||||
|
||||
```yaml
|
||||
- name: Notify Slack
|
||||
if: steps.check_changes.outputs.changes == 'true'
|
||||
uses: slackapi/slack-github-action@v1
|
||||
with:
|
||||
webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
payload: |
|
||||
{
|
||||
"text": "✅ Translations updated for commit ${{ github.sha }}",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "*Translations Updated*\nCommit: <${{ github.event.head_commit.url }}|${{ github.event.head_commit.message }}>"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use incremental mode** in CI/CD to save costs
|
||||
2. **Non-interactive mode** (`-y`) for automation
|
||||
3. **Commit terminology** (`.jta/`) for consistency
|
||||
4. **Set up branch protection** to require CI checks
|
||||
5. **Monitor API usage** and costs
|
||||
6. **Use caching** for jta binary to speed up workflow
|
||||
|
||||
## Cost Optimization
|
||||
|
||||
### Before (Manual Translation)
|
||||
- Developer time: ~2 hours per update
|
||||
- Inconsistent quality
|
||||
- Often delayed or forgotten
|
||||
|
||||
### After (Automated with Jta)
|
||||
- Developer time: 0 (fully automated)
|
||||
- Consistent high quality (Agentic reflection)
|
||||
- Instant updates
|
||||
- API cost: ~$0.15-0.30 per update (incremental)
|
||||
|
||||
### Annual Savings Example
|
||||
|
||||
Assuming:
|
||||
- 50 updates to en.json per year
|
||||
- 5 target languages
|
||||
- ~$0.20 per update (incremental)
|
||||
|
||||
**Cost:**
|
||||
- API: $10/year
|
||||
- Developer time saved: 100 hours/year
|
||||
- ROI: Massive (100+ hours saved vs $10 API cost)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Workflow Fails: "API key not found"
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Ensure secret is set correctly in GitHub
|
||||
# Settings → Secrets → Actions → OPENAI_API_KEY
|
||||
```
|
||||
|
||||
### Workflow Fails: "Permission denied"
|
||||
|
||||
**Solution:**
|
||||
Add write permissions to workflow:
|
||||
```yaml
|
||||
permissions:
|
||||
contents: write # Allow pushing commits
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
**Solution:**
|
||||
Add retry logic or reduce concurrency:
|
||||
```yaml
|
||||
- name: Translate with retry
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
run: |
|
||||
for i in {1..3}; do
|
||||
jta locales/en.json --to zh,ja,ko,es,fr \
|
||||
--incremental \
|
||||
--batch-size 10 \
|
||||
--concurrency 1 \
|
||||
-y && break
|
||||
echo "Retry $i/3 after rate limit..."
|
||||
sleep 60
|
||||
done
|
||||
```
|
||||
303
skills/jta/examples/incremental-mode.md
Normal file
303
skills/jta/examples/incremental-mode.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# Example: Incremental Translation
|
||||
|
||||
This example demonstrates how to update existing translations when you add new content to your source file.
|
||||
|
||||
## Scenario
|
||||
|
||||
User has already translated `en.json` to Chinese (`zh.json`). Now they've added 5 new keys and modified 2 existing keys in `en.json`. They want to update `zh.json` without re-translating everything.
|
||||
|
||||
## User Request
|
||||
|
||||
> "I added new keys to my en.json, please update the Chinese translation"
|
||||
|
||||
## Claude's Workflow
|
||||
|
||||
### Step 1: Understand the Context
|
||||
|
||||
Claude recognizes:
|
||||
- **Task**: Update existing translation
|
||||
- **Source file**: en.json
|
||||
- **Target**: Chinese (zh.json already exists)
|
||||
- **Mode**: Incremental (only translate changes)
|
||||
|
||||
### Step 2: Check Existing Translation
|
||||
|
||||
```bash
|
||||
# Verify both files exist
|
||||
ls -lh locales/en.json locales/zh.json
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
-rw-r--r-- 1 user staff 2.8K en.json (modified 5 minutes ago)
|
||||
-rw-r--r-- 1 user staff 2.6K zh.json (created 2 days ago)
|
||||
```
|
||||
|
||||
### Step 3: Execute Incremental Translation
|
||||
|
||||
```bash
|
||||
# Use incremental mode
|
||||
jta locales/en.json --to zh --incremental
|
||||
```
|
||||
|
||||
### Step 4: Analyze Changes
|
||||
|
||||
Console output:
|
||||
```
|
||||
📄 Loading source file...
|
||||
✓ Source file loaded (105 keys)
|
||||
|
||||
📄 Loading existing translation...
|
||||
✓ Existing translation loaded (98 keys)
|
||||
|
||||
🔍 Analyzing changes...
|
||||
|
||||
Changes detected:
|
||||
📝 New keys: 5
|
||||
✏️ Modified keys: 2
|
||||
✅ Unchanged keys: 93
|
||||
🗑️ Deleted keys: 1
|
||||
|
||||
Breakdown:
|
||||
New keys:
|
||||
- settings.notification.email
|
||||
- settings.notification.push
|
||||
- user.preferences.theme
|
||||
- user.preferences.language
|
||||
- app.features.newFeature
|
||||
|
||||
Modified keys:
|
||||
- app.welcome (content changed)
|
||||
- user.credits (content changed)
|
||||
|
||||
Deleted keys:
|
||||
- app.deprecated (will be removed from translation)
|
||||
|
||||
Continue with incremental translation? [Y/n]
|
||||
```
|
||||
|
||||
### Step 5: User Confirms
|
||||
|
||||
Since the request included "update", Claude proceeds:
|
||||
```bash
|
||||
# Continue (non-interactive with -y would skip prompt)
|
||||
# User presses Y or Claude proceeds automatically
|
||||
```
|
||||
|
||||
### Step 6: Translate Only Changes
|
||||
|
||||
Console output:
|
||||
```
|
||||
📚 Loading terminology...
|
||||
✓ Terminology loaded (8 terms from .jta/)
|
||||
|
||||
🤖 Translating 7 items (5 new + 2 modified)...
|
||||
Processing ━━━━━━━━━━━━━━━━━━━━ 100% (7/7)
|
||||
✓ Translation completed
|
||||
|
||||
🔄 Merging with existing translations...
|
||||
✓ Merged 93 unchanged translations
|
||||
✓ Added 5 new translations
|
||||
✓ Updated 2 modified translations
|
||||
✓ Removed 1 deleted key
|
||||
|
||||
💾 Saving translation...
|
||||
✓ Saved to locales/zh.json
|
||||
```
|
||||
|
||||
### Step 7: Show Statistics
|
||||
|
||||
```
|
||||
📊 Incremental Translation Statistics
|
||||
|
||||
Target: Chinese (zh)
|
||||
Total source keys: 105
|
||||
New keys translated: 5
|
||||
Modified keys: 2
|
||||
Unchanged keys: 93 (preserved from previous translation)
|
||||
Deleted keys: 1 (removed)
|
||||
|
||||
Translation performance:
|
||||
Items translated: 7 (5 + 2)
|
||||
Success: 7
|
||||
Failed: 0
|
||||
Duration: 8s
|
||||
API calls: 2 (1 translate + 1 reflect)
|
||||
|
||||
Cost savings:
|
||||
Without incremental: ~$0.30 (105 keys, 15 API calls)
|
||||
With incremental: ~$0.03 (7 keys, 2 API calls)
|
||||
Saved: ~90% ($0.27)
|
||||
```
|
||||
|
||||
## Claude's Response to User
|
||||
|
||||
```
|
||||
✅ Chinese translation updated successfully!
|
||||
|
||||
I've updated your zh.json with the changes from en.json using incremental mode.
|
||||
|
||||
**Changes applied:**
|
||||
- ✨ Added 5 new translations
|
||||
- ✏️ Updated 2 modified translations
|
||||
- 🗑️ Removed 1 obsolete translation
|
||||
- ✅ Preserved 93 unchanged translations
|
||||
|
||||
**New translations added:**
|
||||
1. `settings.notification.email` → "电子邮件通知"
|
||||
2. `settings.notification.push` → "推送通知"
|
||||
3. `user.preferences.theme` → "主题偏好"
|
||||
4. `user.preferences.language` → "语言偏好"
|
||||
5. `app.features.newFeature` → "新功能"
|
||||
|
||||
**Updated translations:**
|
||||
1. `app.welcome` → "欢迎来到 {appName}!开始您的旅程"
|
||||
2. `user.credits` → "您的账户有 {count} 积分"
|
||||
|
||||
**Performance:**
|
||||
- Duration: 8 seconds (vs ~45s for full re-translation)
|
||||
- API calls: 2 (vs 15 for full re-translation)
|
||||
- Cost: ~$0.03 (vs ~$0.30, saved 90%)
|
||||
|
||||
Your existing high-quality translations were preserved, and only the new/changed content was translated with Agentic reflection for quality assurance.
|
||||
|
||||
Would you like to update other languages as well?
|
||||
```
|
||||
|
||||
## Comparison: Incremental vs Full Translation
|
||||
|
||||
### Full Translation (without --incremental)
|
||||
```bash
|
||||
jta en.json --to zh
|
||||
```
|
||||
- Translates all 105 keys
|
||||
- Takes ~45 seconds
|
||||
- 15 API calls
|
||||
- Cost: ~$0.30
|
||||
- May lose existing manual refinements
|
||||
|
||||
### Incremental Translation (with --incremental)
|
||||
```bash
|
||||
jta en.json --to zh --incremental
|
||||
```
|
||||
- Translates only 7 changed keys
|
||||
- Takes ~8 seconds
|
||||
- 2 API calls
|
||||
- Cost: ~$0.03
|
||||
- Preserves existing translations exactly
|
||||
|
||||
## How Incremental Detection Works
|
||||
|
||||
Jta uses content hashing to detect changes:
|
||||
|
||||
```
|
||||
1. Load source (en.json)
|
||||
2. Load existing translation (zh.json)
|
||||
3. For each key in source:
|
||||
- Calculate content hash of source value
|
||||
- Compare with hash stored in previous translation
|
||||
- If different → mark as "modified"
|
||||
- If not in previous → mark as "new"
|
||||
4. For each key in previous translation:
|
||||
- If not in source → mark as "deleted"
|
||||
5. Translate only "new" + "modified"
|
||||
6. Merge with "unchanged"
|
||||
7. Remove "deleted"
|
||||
```
|
||||
|
||||
## Sample Changes
|
||||
|
||||
### Before (en.json - 2 days ago)
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "Welcome to {appName}!",
|
||||
"deprecated": "Old feature (no longer used)"
|
||||
},
|
||||
"user": {
|
||||
"credits": "You have {count} credits"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### After (en.json - now)
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "Welcome to {appName}! Start your journey",
|
||||
"features": {
|
||||
"newFeature": "New Feature"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"credits": "Your account has {count} credits",
|
||||
"preferences": {
|
||||
"theme": "Theme",
|
||||
"language": "Language"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"notification": {
|
||||
"email": "Email notifications",
|
||||
"push": "Push notifications"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Changes Detected
|
||||
- ✨ **New**: `app.features.newFeature`, `user.preferences.theme`, `user.preferences.language`, `settings.notification.email`, `settings.notification.push`
|
||||
- ✏️ **Modified**: `app.welcome`, `user.credits`
|
||||
- 🗑️ **Deleted**: `app.deprecated`
|
||||
|
||||
### Updated Translation (zh.json)
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"welcome": "欢迎来到 {appName}!开始您的旅程",
|
||||
"features": {
|
||||
"newFeature": "新功能"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"credits": "您的账户有 {count} 积分",
|
||||
"preferences": {
|
||||
"theme": "主题偏好",
|
||||
"language": "语言偏好"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"notification": {
|
||||
"email": "电子邮件通知",
|
||||
"push": "推送通知"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always use incremental mode for updates**
|
||||
```bash
|
||||
jta en.json --to zh --incremental
|
||||
```
|
||||
|
||||
2. **Full re-translation when needed**
|
||||
- After major terminology changes
|
||||
- When quality is unsatisfactory
|
||||
- When starting fresh
|
||||
```bash
|
||||
jta en.json --to zh # without --incremental
|
||||
```
|
||||
|
||||
3. **CI/CD integration**
|
||||
```bash
|
||||
# In your CI pipeline
|
||||
jta locales/en.json --to zh,ja,ko --incremental -y
|
||||
```
|
||||
|
||||
4. **Multiple languages**
|
||||
```bash
|
||||
# Update all languages incrementally
|
||||
jta en.json --to zh,ja,ko,es,fr --incremental -y
|
||||
```
|
||||
118
skills/jta/scripts/install.sh
Executable file
118
skills/jta/scripts/install.sh
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
# Jta Installation Script
|
||||
# Automatically detects OS and architecture, installs jta
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
echo "🚀 Jta Installation Script"
|
||||
echo "=========================="
|
||||
echo ""
|
||||
|
||||
# Detect OS
|
||||
OS="$(uname -s)"
|
||||
ARCH="$(uname -m)"
|
||||
|
||||
echo "Detected system: $OS $ARCH"
|
||||
echo ""
|
||||
|
||||
# Check if jta is already installed
|
||||
if command -v jta &> /dev/null; then
|
||||
CURRENT_VERSION=$(jta --version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
||||
echo "✓ Jta is already installed (version: $CURRENT_VERSION)"
|
||||
read -p "Do you want to reinstall/update? [y/N] " -n 1 -r
|
||||
echo ""
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Installation cancelled."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install based on OS
|
||||
case "$OS" in
|
||||
Darwin*)
|
||||
echo "📦 Installing on macOS..."
|
||||
|
||||
# Try Homebrew first
|
||||
if command -v brew &> /dev/null; then
|
||||
echo "Using Homebrew..."
|
||||
brew tap hikanner/jta 2>/dev/null || true
|
||||
brew install jta || brew upgrade jta
|
||||
else
|
||||
echo "Homebrew not found, downloading binary..."
|
||||
|
||||
# Determine architecture
|
||||
if [[ "$ARCH" == "arm64" ]]; then
|
||||
BINARY="jta-darwin-arm64"
|
||||
else
|
||||
BINARY="jta-darwin-amd64"
|
||||
fi
|
||||
|
||||
# Download binary
|
||||
echo "Downloading $BINARY..."
|
||||
curl -L "https://github.com/hikanner/jta/releases/latest/download/$BINARY" -o jta
|
||||
|
||||
# Make executable
|
||||
chmod +x jta
|
||||
|
||||
# Move to PATH
|
||||
echo "Installing to /usr/local/bin/ (may require sudo password)..."
|
||||
sudo mv jta /usr/local/bin/
|
||||
fi
|
||||
;;
|
||||
|
||||
Linux*)
|
||||
echo "📦 Installing on Linux..."
|
||||
|
||||
# Determine architecture
|
||||
if [[ "$ARCH" == "x86_64" ]]; then
|
||||
BINARY="jta-linux-amd64"
|
||||
elif [[ "$ARCH" == "aarch64" ]] || [[ "$ARCH" == "arm64" ]]; then
|
||||
BINARY="jta-linux-arm64"
|
||||
else
|
||||
echo "❌ Unsupported architecture: $ARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Download binary
|
||||
echo "Downloading $BINARY..."
|
||||
curl -L "https://github.com/hikanner/jta/releases/latest/download/$BINARY" -o jta
|
||||
|
||||
# Make executable
|
||||
chmod +x jta
|
||||
|
||||
# Move to PATH
|
||||
echo "Installing to /usr/local/bin/ (may require sudo password)..."
|
||||
sudo mv jta /usr/local/bin/
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "❌ Unsupported operating system: $OS"
|
||||
echo "Please visit https://github.com/hikanner/jta for manual installation instructions."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "✅ Installation complete!"
|
||||
echo ""
|
||||
|
||||
# Verify installation
|
||||
if command -v jta &> /dev/null; then
|
||||
VERSION=$(jta --version 2>&1 | head -1)
|
||||
echo "Installed version: $VERSION"
|
||||
echo ""
|
||||
echo "🎉 You can now use jta!"
|
||||
echo ""
|
||||
echo "Quick start:"
|
||||
echo " jta en.json --to zh,ja,ko"
|
||||
echo ""
|
||||
echo "For help:"
|
||||
echo " jta --help"
|
||||
echo ""
|
||||
echo "⚠️ Don't forget to set your API key:"
|
||||
echo " export OPENAI_API_KEY=sk-..."
|
||||
else
|
||||
echo "❌ Installation verification failed"
|
||||
echo "Please check the error messages above and try again."
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user