···1111v-00010 March
1212v-00011 entrance;entry;gate;approach;mouth
1313v-00012 exit;gateway;way out
1414-v-00015 input;(data) entry
1414+v-00015 input;data entry
1515v-00016 garden which contains an artificial hill and a pond
1616v-00017 workman;craftsman;laborer;labourer;artisan
1717v-00018 taking up a lot of space
-75
data/scripts/rename_audio.ts
···11-/**
22- * Script to rename existing audio files from old numeric-id format to new string-id format.
33- *
44- * Old format: 00001_zh-CN_zh-CN-XiaoxiaoNeural.mp3 (v2 numeric id, zero-padded to 5 digits)
55- * New format: c-00001_zh-CN_zh-CN-XiaoxiaoNeural.mp3 (new string id)
66- *
77- * Run from repo root: deno run -A data/scripts/6_rename_audio.ts
88- */
99-import { join } from '@std/path'
1010-import { readDict } from './utils/fs.ts'
1111-1212-const AUDIO_ROOT = 'www/static/gen/audio'
1313-const LOCALES = ['zh_CN', 'zh_HK', 'zh_TW']
1414-1515-// Build a map from old v2 numeric id → new string id, covering both characters and vocabulary
1616-const v2ToNewId = new Map<number, string>()
1717-1818-for (const path of ['lang/characters.tsv', 'lang/vocabulary.tsv']) {
1919- for (const { id, v2 } of readDict(path)) {
2020- if (v2 != null) v2ToNewId.set(v2, id)
2121- }
2222-}
2323-2424-let renamed = 0
2525-let skipped = 0
2626-2727-for (const locale of LOCALES) {
2828- const dir = join(AUDIO_ROOT, locale)
2929-3030- let entries: Deno.DirEntry[]
3131- try {
3232- entries = Array.from(Deno.readDirSync(dir))
3333- } catch {
3434- console.warn(`Skipping ${dir} (not found)`)
3535- continue
3636- }
3737-3838- for (const entry of entries) {
3939- if (!entry.name.endsWith('.mp3')) continue
4040-4141- // Old format: "00001_zh-CN_zh-CN-XiaoxiaoNeural.mp3"
4242- // New format already: "c-00001_zh-CN_..." — skip if already renamed
4343- if (/^[cv]-\d{5}_/.test(entry.name)) {
4444- skipped++
4545- continue
4646- }
4747-4848- // Parse the old numeric id from the filename
4949- const oldNumStr = entry.name.split('_')[0]
5050- const oldNum = parseInt(oldNumStr, 10)
5151- if (isNaN(oldNum)) {
5252- console.warn(`Unrecognized filename, skipping: ${entry.name}`)
5353- skipped++
5454- continue
5555- }
5656-5757- const newId = v2ToNewId.get(oldNum)
5858- if (!newId) {
5959- console.warn(`No mapping found for v2=${oldNum} (${entry.name}), skipping`)
6060- skipped++
6161- continue
6262- }
6363-6464- // Replace just the leading numeric prefix with the new string id
6565- const newName = entry.name.replace(oldNumStr, newId)
6666- const oldPath = join(dir, entry.name)
6767- const newPath = join(dir, newName)
6868-6969- Deno.renameSync(oldPath, newPath)
7070- console.log(` ${entry.name} → ${newName}`)
7171- renamed++
7272- }
7373-}
7474-7575-console.log(`\nDone. Renamed: ${renamed}, Skipped: ${skipped}`)