Files
dashboard/batch-i18n.py
sakuradairong fdc7af186e fix(i18n): localize peer SSH, edit IP, routes, access tokens and setup keys
- Localize PeerEditIPModal config and buttons
- Localize PeerSSHToggle dialogs, tooltips, help text and callouts
- Localize AddRouteDropdownButton and RemoteJobDropdownButton
- Localize PeerRoutesTable and RouteMetricCell tooltips
- Localize AccessTokensTable empty state
- Localize SetupKeysTable filters, options and empty states
- Add missing translation keys to en.ts and zh.ts
- Fix t.rich tag usage for peerOfflineRemoteJob
- Fix singularize usage with ICU plural activePoliciesCount
- Normalize formatting with prettier
- Remove empty progress.md
2026-06-23 23:12:27 +08:00

104 lines
4.6 KiB
Python

"""Batch i18n localization for remaining simple files"""
import re, os
os.chdir('/root/github_projects/dashboard')
# Helper: replace first occurrence after a marker
def replace_in_file(filepath, replacements):
with open(filepath) as f:
content = f.read()
changed = False
for old, new in replacements:
if old in content:
content = content.replace(old, new, 1)
changed = True
print(f" {os.path.basename(filepath)}: replaced '{old[:40]}'")
else:
print(f" WARN: '{old[:40]}' not in {os.path.basename(filepath)}")
if changed:
with open(filepath, 'w') as f:
f.write(content)
# === 1. AddRouteDropdownButton.tsx ===
replace_in_file('src/modules/peer/AddRouteDropdownButton.tsx', [
('import Button from "@components/Button";',
'import { useTranslations } from "next-intl";\nimport Button from "@components/Button";'),
('export default function AddRouteDropdownButton() {',
'export default function AddRouteDropdownButton() {\n const t = useTranslations("common");'),
('New Network Route', '{t("newNetworkRoute")}'),
('Existing Network', '{t("existingNetwork")}'),
])
# === 2. RemoteJobDropdownButton.tsx ===
replace_in_file('src/modules/peer/RemoteJobDropdownButton.tsx', [
('import Button from "@components/Button";',
'import { useTranslations } from "next-intl";\nimport Button from "@components/Button";'),
('export const RemoteJobDropdownButton = () => {',
'export const RemoteJobDropdownButton = () => {\n const t = useTranslations("common");'),
('Debug Bundle', '{t("debugBundle")}'),
])
# === 3. RouteMetricCell.tsx ===
replace_in_file('src/modules/routes/RouteMetricCell.tsx', [
('import FullTooltip from "@components/FullTooltip";',
'import { useTranslations } from "next-intl";\nimport FullTooltip from "@components/FullTooltip";'),
('export default function RouteMetricCell({',
'export default function RouteMetricCell({\n const t = useTranslations("common");'),
('Lower metrics have higher priority.', '{t("metricPriority")}'),
])
# === 4. PeerRoutesTable.tsx ===
replace_in_file('src/modules/peer/PeerRoutesTable.tsx', [
('import Card from "@components/Card";',
'import { useTranslations } from "next-intl";\nimport Card from "@components/Card";'),
('export const RouteTableColumns: ColumnDef<Route>[] = [',
'function RouteTableColumns(t: ReturnType<typeof useTranslations>): ColumnDef<Route>[] {\n return ['),
('];\n\nexport default function PeerRoutesTable({',
'];\n}\n\nexport default function PeerRoutesTable({'),
('export default function PeerRoutesTable({',
'export default function PeerRoutesTable({\n const t = useTranslations("common");'),
('];\n\nfunction RouteTableColumns', '];\n}\n\nfunction RouteTableColumns'), # fix double close
])
# Replace column headers in PeerRoutesTable
with open('src/modules/peer/PeerRoutesTable.tsx') as f:
c = f.read()
c = c.replace('DataTableHeader column={column}>Name<', 'DataTableHeader column={column}>{t("name")}<')
c = c.replace('DataTableHeader column={column}>Network<', 'DataTableHeader column={column}>{t("network")}<')
c = c.replace('DataTableHeader column={column}>Distribution Groups<', 'DataTableHeader column={column}>{t("distributionGroups")}<')
c = c.replace('DataTableHeader column={column}>Active<', 'DataTableHeader column={column}>{t("active")}<')
with open('src/modules/peer/PeerRoutesTable.tsx', 'w') as f:
f.write(c)
print(" PeerRoutesTable: column headers replaced")
# === 5. Add keys to en.ts ===
with open('src/i18n/messages/en.ts') as f:
en = f.read()
# Add to common namespace (after debugBundle or similar)
if 'debugBundle' not in en:
en = en.replace(
'routingPeer: "Routing Peer",',
'routingPeer: "Routing Peer",\n newNetworkRoute: "New Network Route",\n existingNetwork: "Existing Network",\n debugBundle: "Debug Bundle",\n metricPriority: "Lower metrics have higher priority.",'
)
with open('src/i18n/messages/en.ts', 'w') as f:
f.write(en)
print(" en.ts: keys added")
# === 6. Add keys to zh.ts ===
with open('src/i18n/messages/zh.ts') as f:
zh = f.read()
if 'debugBundle' not in zh:
zh = zh.replace(
'routingPeer: "路由节点",',
'routingPeer: "路由节点",\n newNetworkRoute: "新网络路由",\n existingNetwork: "现有网络",\n debugBundle: "调试包",\n metricPriority: "较低的度量值具有更高的优先级。"'
)
with open('src/i18n/messages/zh.ts', 'w') as f:
f.write(zh)
print(" zh.ts: Chinese translations added")
print("\nDone!")