Translation Workflow
This page covers core translation operations: translate single file, translate folder, consistency check, and rollback.
Load Locale Files
Optional: A preparatory step before translation, automatically loads JSON files from specified directories. Below are common approaches for webpack and vite:
webpack
const enContext = require.context('./module', true, /\/en-US\.json$/)
const zhContext = require.context('./module', true, /\/zh-CN\.json$/)
const contextToModuleMap = (context) => Object.fromEntries(context.keys().map((key) => [key, context(key)]))
const enMds = contextToModuleMap(enContext)
const zhMds = contextToModuleMap(zhContext)
const getLocaleCollect = (m) => Object.values(m).reduce((o, k) => ({ ...o, ...k }), {})
const enUsCollect = getLocaleCollect(enMds)
const zhCnCollect = getLocaleCollect(zhMds)vite
const enMds = import.meta.glob('./module/**/en-US.json', { eager: true, import: 'default' })
const zhMds = import.meta.glob('./module/**/zh-CN.json', { eager: true, import: 'default' })
const getLocaleCollect = (m) => Object.values(m).reduce((o, k) => ({ ...o, ...k }), {})
const enUsCollect = getLocaleCollect(enMds)
const zhCnCollect = getLocaleCollect(zhMds)Translate Single File
hitf tf translates a single file. It extracts source language text, generates keys, writes locale files, and replaces source text with internationalization calls.
By default, it works with Chinese source code projects. Configure locales: ["en-US", "zh-CN", "ja-JP"] to extract English text and translate to zh-CN and ja-JP.
Basic Command
hitf tf views\demo\index.vueSupported file types:
| Type | Description |
|---|---|
.vue | Vue SFC, including <template>, <script>, <script setup> |
.js / .ts | JavaScript and TypeScript business code |
.jsx / .tsx | React JSX / TSX |
.json | JSON text values |
Basic Options
hitf tf src\views\demo\index.vue demo -d
hitf tf src\views\demo\index.vue demo -i
hitf tf src\views\demo\index.vue demo -r .hitf\reports\demo.json
hitf tf apps\main\src\views\index.vue home -p main| Option | Short | Description |
|---|---|---|
-n, --name <name> | -n | i18n namespace key (defaults to parent directory name) |
-p, --project <project> | -p | Specify project when outDir is an object |
-d, --dry-run | -d | Preview only: list extracted texts with locations; no translation or file writes |
-i, --interactive | -i | Select texts to translate in a tree; deselected items get ignore comments automatically and are skipped |
-r, --report <file> | -r | Write JSON translation report |
-v, --verbose | -v | Output detailed logs |
Dry-run Mode
-d / --dry-run previews the translation plan only: no API calls, no file writes. For a single file, tf lists each extracted text with its source location (file:line:column), followed by skipped (non-extracted) strings with reasons:
hitf tf src\views\demo\index.vue -dOutput example:
suitable → src/views/demo/index.vue:2:21
test → src/views/demo/index.vue:3:21tf -d does not generate locale files or modify source code, so it is a good way to review the extraction scope before translating.
Interactive Selection
-i / --interactive shows a tree checkbox for choosing which texts to translate. Only selected items participate in translation and get keys; deselected items are marked as ignored in place and are skipped on subsequent extractions:
hitf tf src\views\demo\index.vue demo -iKey bindings:
| Key | Action |
|---|---|
↑ / ↓ | Move up / down |
← / → | Collapse / expand a group |
Space | Toggle: leaf toggles itself; a group toggles its whole branch (◉ all / ◐ partial / ◯ none) |
Ctrl+A | Select all visible leaves |
Ctrl+I (also Tab) | Invert visible leaves |
Enter | Confirm (at least 1 item must be selected) |
| any character | Filter by text; Backspace removes the search term |
After confirmation, only selected items are translated. Deselected items trigger the message "N texts skipped (ignore comments will be added)" and ignore comments are inserted automatically (see Ignore Comments below):
- JS / TS:
/* @hitf-i18n-ignore-start */…/* @hitf-i18n-ignore-end */ - Vue template text:
<!-- @hitf-i18n-ignore-start -->…<!-- @hitf-i18n-ignore-end --> - JSX:
{/* @hitf-i18n-ignore-start */}…{/* @hitf-i18n-ignore-end */} - Vue template static attributes:
<!-- @hitf-i18n-ignore:prop:<attrName> -->placed directly above the target tag - JSON files: no comments can be inserted; entries are recorded in
.hitf/i18n-ignore.jsonand filtered automatically on later runs
If the interaction is interrupted (e.g. Ctrl+C), the translation is aborted with no writes.
Extraction Scope
Extracts user-visible or runtime-displayed text:
message.success('Save successfully')
toast('Copied')
const item = {
label: 'User Name',
title: 'User Detail',
placeholder: 'Enter username',
description: 'Please select a user'
}Supports fallback text in logical expressions:
const text = data?.text || 'Default text'
const desc = data?.description ?? 'No description'Also supported in Vue templates:
{{ data?.text || 'Default text' }}
{{ data?.description ?? 'No description' }}Destructuring defaults and function parameter defaults are not extracted by default, to avoid mistaking type/data structure fallbacks for UI text:
const { propertyName = 'User name' } = objectToDestruct
function submit(label = 'Save') {}Vue Template
Text nodes are replaced with $t:
<button>登录</button><button>{{ $t('demo.login') }}</button>Chinese next to interpolation preserves expression boundaries:
<h1>留言({{ remarkList ? remarkList.length : 0 }})</h1><h1>{{ $t('demo.leave_a_message') }}({{ remarkList ? remarkList.length : 0 }})</h1>Attributes
User-visible attributes are translated:
<input placeholder="请输入用户名" /><input :placeholder="$t('demo.please_enter_username')" />Resource path attributes are not translated, to avoid breaking file references:
<img src="@/assets/images/ssHome/供应商总数量1.png" alt="供应商总数量" /><img src="@/assets/images/ssHome/供应商总数量1.png" :alt="$t('demo.total_number_of_suppliers')" />Currently skipped resource attributes include src, srcset, href, poster.
Style-related content is skipped, including class, dynamic classes, inline style, and <style> blocks:
<div class="user-card" :style="{ color: 'red' }">用户详情</div>
<style lang="scss" scoped>
.user-card {}
</style>JavaScript Strings
Source language strings in scripts are replaced with translation function calls:
const title = '登录'const title = t('demo.login')English source example:
{
"translationSetting": {
"locales": ["en-US", "zh-CN", "ja-JP"]
}
}<button>Login</button><button>{{ $t('demo.login') }}</button>Chinese in regex is part of matching rules, not recommended for automatic translation:
const regex = /中文|English/giuAlready processed $t(...), this.$t(...), t(...) are skipped. Vue2's this.$t is still supported.
JSX
JSX text is replaced with {t(...)}:
<h1>留言({remarkList ? remarkList.length : 0})</h1><h1>{t('jsxAll.leave_a_message')}({remarkList ? remarkList.length : 0})</h1>Long natural language should be processed as a complete unit, to avoid splitting into too many keys by commas or periods.
In JSX/TSX, className, style, event attributes, type, role, data-*, aria-* are skipped; custom display attributes can be extracted:
<Comp title="User Detail" label="User Name" />Vue SFC's <script setup lang="jsx"> and <script setup lang="tsx"> are also parsed as JSX/TSX, supporting render functions and JSX text returned from defineComponent.
Ignore Comments
Use ignore comments for code you don't want processed temporarily:
// @hitf-i18n-ignore-next
message.success('Keep original')
/* @hitf-i18n-ignore-start */
const a = 'Keep original'
const b = 'Keep original too'
/* @hitf-i18n-ignore-end */Vue template:
<!-- @hitf-i18n-ignore-next -->
<div>保持原文</div>Ignore entire file:
// @hitf-i18n-ignore-fileDirectives:
| Directive | Effect |
|---|---|
@hitf-i18n-ignore-next | Ignore the next extractable segment |
@hitf-i18n-ignore-start / -end | Ignore all texts in the range |
@hitf-i18n-ignore-file | Ignore the entire file |
@hitf-i18n-ignore:prop:<attrName> | Ignore a specific static attribute in Vue templates (e.g. <!-- @hitf-i18n-ignore:prop:placeholder -->) |
These comments can also be inserted automatically by -i deselection: /* */ for JS / TS, <!-- --> for Vue templates, {/* */} for JSX, and <!-- @hitf-i18n-ignore:prop:<attrName> --> above the target tag for Vue template static attributes. JSON files cannot contain comments, so deselected items are recorded in .hitf/i18n-ignore.json and filtered automatically on later runs.
Output
Translation typically produces two types of changes:
- Chinese in the original file is replaced with
$tortcalls. - Corresponding locale files are generated in the locale directory.
Example:
src\locale\module\demo\zh-CN.json
src\locale\module\demo\en-US.jsonTranslate Folder
hitf tfo recursively translates an entire folder.
Basic Command
hitf tfo src\viewsRecursively processes all .vue, .js, .ts, .jsx, .tsx, .json files.
Common Options
# Dry-run mode
hitf tfo src\views demo -d
# Interactive confirmation
hitf tfo src\views demo -i
# Generate report
hitf tfo src\views demo -r .hitf\reports\demo.json| Option | Short | Description |
|---|---|---|
-n, --name <name> | -n | i18n namespace key (defaults to parent directory name) |
-p, --project <project> | -p | Specify project when outDir is an object |
-d, --dry-run | -d | Preview only: list extracted texts with locations; no translation or file writes |
-i, --interactive | -i | Select texts to translate in a tree; deselected items get ignore comments automatically and are skipped |
-r, --report <file> | -r | Write JSON translation report |
-v, --verbose | -v | Output detailed logs |
Folder Preview (Tree Browse)
After scanning, tfo -d shows a read-only tree of the three-level plan directory > file > text (leaves are marked [tr] and are all translated by default):
hitf tfo src\views demo -dTree keys: ↑/↓ move · ←/→ collapse/expand · type to search · Enter to finish. After closing, it prints the total number of texts to translate and skipped-string details per file. No translation is performed and no files are written.
In a non-TTY environment (scripts / CI / pipes),
tfo -dskips the interactive tree and falls back to a static tree printout; the preview output is still complete.
Folder Interactive Selection
tfo -i uses a tree checkbox organized as directory > file > text to choose which texts to translate; deselected items get ignore comments automatically (same behavior as single-file tf -i, see Interactive Selection above):
hitf tfo src\views demo -iExclude Files
Use --exclude to exclude specific files:
hitf tfo src --exclude "**/*.test.js"Batch Output
Translation results are written to the corresponding namespace directory under outDir:
src\locale\module\demo\zh-CN.json
src\locale\module\demo\en-US.jsonConsistency Check
hitf tcheck checks whether $t(...), this.$t(...), t(...) references in source code match locale JSON files.
Basic Command
hitf tcheck src
hitf tcheck src -r .hitf\reports\tcheck.jsonCheck Content
| Type | Description |
|---|---|
| missing | Keys referenced in source but missing from all locale files |
| unused | Keys present in locale files but not referenced in source |
| inconsistent | Keys missing from some locale JSON files |
| invalid locale files | Unparseable JSON locale files |
Output Example
Translation check summary
missing: 2
unused: 0
inconsistent: 0
invalid locale files: 0
missing hello
src/App.vue:2:11
missing welcome
src/App.vue:3:9tcheck is suitable for running after batch migration, and can be added to CI to prevent missing locale files or corrupted JSON from entering the main branch.
Rollback
hitf rollback undoes the last translation operation.
Basic Command
hitf rollback # Rollback the latest
hitf rollback -l # List available backups
hitf rollback -n xxx # Rollback a specific backup
hitf rollback -k 5 # Keep only 5 most recent backupsOptions
| Option | Short | Description |
|---|---|---|
-l, --list | -l | List all available backups |
-n, --name <name> | -n | Rollback a specific backup by name |
-k, --keep <count> | -k | Keep only N most recent backups |
Use Cases
- Unsatisfactory translation results: Rollback and adjust configuration before re-translating
- Recovery from mistakes: Rollback to the state before translation
- Backup management: Clean up old backups to free space
Translation Reports
Both tf and tfo support -r, --report <file> to generate translation reports:
hitf tf src\views\user\index.vue user -d -r .hitf\reports\user.json
hitf tfo src\views user -r .hitf\reports\user-folder.jsonReports are in JSON format, suitable for manual review, CI upload, or script processing:
{
"mode": "dry-run",
"summary": {
"filesScanned": 1,
"filesWithExtractions": 1,
"replacements": 3,
"written": 0,
"skipped": 1,
"failed": 0
},
"files": [
{
"file": "src/views/user/index.vue",
"outputFile": ".hitf/lang/user/index.vue",
"replacements": [
{
"text": "User Detail",
"key": "user.user_detail",
"context": "attribute",
"start": 42,
"end": 53
}
]
}
],
"failedFiles": []
}Field descriptions:
| Field | Description |
|---|---|
mode | dry-run or write |
summary.filesScanned | Number of files actually scanned |
summary.filesWithExtractions | Number of files with extraction results |
summary.replacements | Number of texts to be replaced or already replaced |
summary.written | Number of files written |
summary.skipped | Number of files skipped |
summary.failed | Number of files failed |
files[].replacements | Extracted text, key, context, and position for each file |
failedFiles | Files that failed syntax validation or processing |