hias-cli Translation Feature Design
Many frontend projects don't fully plan internationalization from the start. After some business development, pages, dialogs, buttons, status messages, and prompts are scattered across Vue, React, JSX, utility functions, and configuration objects. Manual migration at this point is labor-intensive and easy to miss.
hias-cli's translation capability is designed for this stage: it doesn't simply search for Chinese and replace it, but tries to understand syntax boundaries in different files, migrating source language text into internationalization calls and generating maintainable locale files. Source code can be Chinese or English; English source uses stricter UI text identification to avoid mistaking protocol values, class names, paths, and type values for translatable text.
Core Flow
A single hias tf roughly follows four steps:
- Read the source file and determine file type.
- Extract text based on source language, preserving each text's position in source.
- Generate keys, query cache or translation service, write locale files.
- Replace Chinese in source file with
$tortcalls.
This flow seems straightforward, but the difficulty lies in "text boundaries."
Why Regex Alone Isn't Enough
Chinese can appear in many places:
<button>登录</button><input placeholder="请输入用户名" /><h1>留言({remarkList ? remarkList.length : 0})</h1>const message = '保存成功'Their replacement syntax differs. Vue template text needs {{ $t(...) }}, attributes need dynamic binding, JSX text needs {t(...)}, JS strings need expression calls.
Using regex alone easily mishandles file paths, regex expressions, comments, style class names, TypeScript types, and interpolation punctuation.
Cache First
In real projects, machine translation only solves part of the problem. Menu names, status names, button names, and industry terminology usually need consistent expressions.
Therefore hias-cli supports importing company translation tables first:
hias tci .\.hias\company.xlsxRecommended format:
| zh-CN | en-US | ja-JP |
|---|---|---|
| 登录 | Login | ログイン |
| 正常状态 | Normal Status | 正常状態 |
After import, the cache is organized by language direction:
{
"zh-CN|en-US": {
"登录": "Login"
},
"zh-CN|ja-JP": {
"登录": "ログイン"
}
}This way the translation process prioritizes the human glossary, and calls the translation service or falls back to source text when missing.
Boundary-Oriented Extraction
What really affects the experience in translation migration is often the boundary details.
For example:
<h1>留言({{ remarkList ? remarkList.length : 0 }})</h1>The ideal result isn't swallowing the left parenthesis into the text:
<h1>{{ $t('demo.leave_a_message') }}{{ remarkList ? remarkList.length : 0 }})</h1>But rather:
<h1>{{ $t('demo.leave_a_message') }}({{ remarkList ? remarkList.length : 0 }})</h1>Another example is resource paths:
<img src="@/assets/images/ssHome/供应商总数量.png" alt="供应商总数量" />src is a file reference and shouldn't be translated; alt is visible semantics and can be translated.
Current extraction further handles:
- JS/TS/JSX/TSX and Vue SFC
- Vue
<script setup lang="jsx">and<script setup lang="tsx"> - Template literals, optional chaining,
||and??fallback text - JSX/TSX text nodes and custom display attributes
- Vue template display text and display attributes
- Already processed
$t(...),this.$t(...),t(...)are skipped - Comments, regex, styles, class/className, style, resource paths, TS type syntax are skipped
When you don't want certain code processed automatically, use:
// @hias-i18n-ignore-next
/* @hias-i18n-ignore-start */
/* @hias-i18n-ignore-end */
// @hias-i18n-ignore-fileReports and Consistency Checks
During batch migration, whether extraction is comprehensive, which files failed, and whether locale files are missing keys all need machine-readable results.
tf / tfo support JSON report output:
hias tfo src\views views --dry-run --report .hias\reports\views.jsonAfter translation, run:
hias tcheck src --report .hias\reports\tcheck.jsonIt checks for keys referenced in source but missing from locale files, keys present in locale files but unreferenced in source, keys inconsistent across locale JSON files, and unparseable JSON files.