PageSourceSearch

https://fairus-stepaudio-3-music.hf.space/studio/assets/js/i18n.js

js fairus-stepaudio-3-music.hf.space collected 2026-10-03 16:51:24 UTC 19,617 bytes, 433 lines download raw bytes

1/* =============================================================================
2   双语字典 i18n —— 默认中文
3   -----------------------------------------------------------------------------
4   用法:t('nav.home');带插值:t('create.elapsed', {time:'1:12'})
5   DOM 上写 data-i18n="key" 即可自动填充(见 main.js applyI18n)。
6   注意:首页标语固定英文,不进字典(见 pages/home.js)。
7   ============================================================================= */
8
9export const DEFAULT_LANG = 'en';
10
11const DICT = {
12  zh: {
13    'app.title': 'StepAudio-3-Music · AI 音乐生成',
14    'brand.name': 'StepAudio 3',
15    'brand.sub': 'Music',
16
17    'nav.home': '首页',
18    'nav.listen': '聆听',
19    'nav.create': '创作',
20    'nav.library': '曲库',
21    'nav.contact': '联系',
22    'nav.arxiv': 'ArXiv',
23    'nav.api': 'API 文档',
24    'nav.apikey': 'API 配置',
25    'nav.collapse': '收起',
26    'nav.expand': '展开',
27
28    /* ── API Key 配置(访客自备 Key,见 config.js)── */
29    'key.title': 'API 配置',
30    'key.promo': '还没有 Key?前往阶跃开放平台注册,可领取免费 API 额度。',
31    'key.goPlatform': '立即前往',
32    'key.label': 'API Key',
33    'key.placeholder': '粘贴你的 API Key',
34    'key.current': '当前已配置:',
35    'key.privacy': 'Key 只保存在你自己的浏览器里,不会上传到任何服务器,也不会写进代码仓库。',
36    'key.show': '显示 Key',
37    'key.hide': '隐藏 Key',
38    'key.save': '保存并校验',
39    'key.clear': '清除',
40    'key.verifying': '正在校验…',
41    'key.ok': '校验通过,可以开始创作了。',
42    'key.saved': 'API Key 已保存',
43    'key.savedThrottled': 'API Key 已保存(当前接口限流,稍后再试生成)',
44    'key.cleared': 'API Key 已清除',
45    'key.err.key_empty': '请先填入 API Key。',
46    'key.err.key_invalid': '这个 Key 无效,请检查是否复制完整。',
47    'key.err.key_no_music': '这个 Key 有效,但账号还没有音乐模型(step-music)的权限。',
48    'key.err.key_timeout': '校验超时,请检查网络后重试。',
49    'key.err.network': '连不上接口,请检查网络后重试。',
50    'key.err.offline': '网络已断开,连上后再试。',
51    'key.err.service_unavailable': '服务暂时不可用,稍后再校验。',
52    'key.needTitle': '还没配置 API Key',
53    'key.needBody': '生成音乐需要你自己的阶跃 API Key。去配置一下,一分钟就好 —— 开放平台可以领免费额度。',
54    'key.later': '稍后再说',
55    'key.goSetup': '去配置',
56
57    'home.placeholder': '雨后的城市夜景,轻快的 City Pop,女声主唱,电钢琴与复古合成器…',
58    'home.instrumental': '纯音乐',
59    'home.dice': '随机灵感',
60    'home.create': '创作',
61    'home.shuffle': '换一批',
62    'home.featured': '精选作品',
63
64    'listen.title': '聆听',
65    'listen.lead': '四种能力,每种五首示例。需要输入音频的能力,可以先听输入再听输出。',
66    'listen.in': '输入',
67    'listen.arrow': '→',
68    'sec.song': '歌曲创作',
69    'sec.song.desc': '一句风格描述,可选歌词,生成带人声的完整歌曲。',
70    'sec.song.in': '文字',
71    'sec.instrumental': '纯音乐创作',
72    'sec.instrumental.desc': '不含人声的器乐作品,适合做背景音乐与配乐。',
73    'sec.instrumental.in': '文字',
74    'sec.vocal2music': '清唱配乐',
75    'sec.vocal2music.desc': '旋律跟随你的清唱,模型补齐编曲与混音。',
76    'sec.vocal2music.in': '清唱 + 文字',
77    'sec.cover': '歌曲翻唱',
78    'sec.cover.desc': '保留参考歌曲的旋律,换一套风格与编曲。',
79    'sec.cover.in': '歌曲 + 文字',
80    'sec.out.song': '整曲',
81    'sec.out.instrumental': '器乐',
82
83    'create.title': '创作',
84    'create.tab.song': '歌曲创作',
85    'create.tab.vocal2music': '清唱配乐',
86    'create.tab.cover': '歌曲翻唱',
87    'create.about.song': '输入歌词和提示词,生成你的专属歌曲。',
88    'create.about.vocal2music': '上传一段清唱,结合歌词和提示词生成完整编曲。',
89    'create.about.cover': '上传原曲,修改这首歌的风格。',
90    'create.title2': '歌曲标题',
91    'create.titlePlaceholder': '留空则自动命名',
92    'create.hint.vocal2music': '输入上传 Vocal 对应的 Lyrics 生成效果更佳!',
93    'create.hint.cover': '输入原曲 Music 对应的 Lyrics 生成效果更佳!',
94    'create.desc': '音乐描述',
95    'create.required': '必填',
96    'create.optional': '选填',
97    'create.descPlaceholder': '描述风格、情绪、乐器、调式…',
98    'create.lyrics': '歌词',
99    'create.lyricsPlaceholder': '[Verse]\n\n[Chorus]',
100    'create.lyricsAuto': '留空则由模型自动作词',
101    'create.instrumental': '纯音乐',
102    'create.instrumentalHint': '生成不含人声的器乐',
103    'create.upload.vocal': '清唱音频',
104    'create.upload.vocalHint': '上传一段无伴奏清唱',
105    'create.upload.song': '参考歌曲',
106    'create.upload.songHint': '上传一首完整成品歌曲',
107    'create.upload.formats': '支持 wav / flac / mp3 / opus',
108    'create.upload.replace': '换一个文件',
109    'create.note.vocal2music': '歌词要和你上传的清唱内容对得上。',
110    'create.note.cover': '歌词要和参考歌曲唱的一致。',
111    'create.advanced': '高级选项',
112    'create.format': '输出格式',
113    'create.bitrate': '码率 (kbps)',
114    'create.submit': '开始创作',
115    'create.submitting': '提交中…',
116    'create.session': '本次创作',
117    'create.sessionEmpty': '这里会显示你这次创作的作品。',
118    'create.viewAll': '查看全部作品',
119    'create.quotaLeft': '今日剩余 {n} 次',
120    'create.quotaOut': '今日额度已用完,明天再来。',
121    'create.noKey': '还没配置 API Key —— 点「开始创作」按提示配置。',
122
123    'status.uploading': '上传中',
124    'status.pending': '排队中',
125    'status.running': '生成中',
126    'status.success': '已完成',
127    'status.failed': '失败',
128    'status.elapsed': '已等待 {time}',
129    'status.hint': '通常需要 1–3 分钟。可以切到别的页面继续听,任务在后台继续。',
130    'status.retry': '重试',
131    'status.cancel': '取消',
132
133    'confirm.delete': '确认删除',
134    'confirm.deleteBody': '删除后无法恢复。',
135    'confirm.deleteOk': '删除',
136    'confirm.cancel': '取消',
137    'confirm.clear': '清空曲库',
138    'confirm.clearBody': '将删除全部作品,无法恢复。',
139    'player.delete': '删除',
140    'library.title': '曲库',
141    'library.lead': '你创作的作品保存在这台设备的浏览器里。',
142    'library.empty': '曲库还是空的',
143    'library.emptyHint': '去创作第一首。',
144    'library.emptyCta': '开始创作',
145    'library.all': '全部',
146    'library.clear': '清空曲库',
147    'library.clearConfirm': '确定清空全部作品?此操作无法撤销。',
148    'library.count': '{n} 首',
149
150    'player.play': '播放',
151    'player.pause': '暂停',
152    'player.prev': '上一首',
153    'player.next': '下一首',
154    'player.like': '喜欢',
155    'player.unlike': '取消喜欢',
156    'player.download': '下载',
157    'player.repeat.off': '顺序播放',
158    'player.repeat.all': '列表循环',
159    'player.repeat.one': '单曲循环',
160    'player.volume': '音量',
161    'player.mute': '静音',
162    'player.unmute': '取消静音',
163    'player.expand': '展开',
164    'player.collapse': '收起',
165    'player.close': '关闭',
166    'player.progress': '播放进度',
167
168    'np.lyrics': '歌词',
169    'np.noLyrics': '这是纯音乐,没有歌词。',
170    'np.caption': '描述',
171    'np.input': '输入音频',
172    'np.noLyricsGiven': '这首没有提供歌词。',
173    'np.input.vocal_audio': '清唱',
174    'np.input.song_audio': '参考歌曲',
175
176    'toast.liked': '已加入喜欢',
177    'toast.unliked': '已取消喜欢',
178    'toast.downloaded': '开始下载',
179    'toast.recipe': '已填入灵感,可以继续改',
180    'toast.noDesc': '请先写音乐描述',
181    'toast.noAudio': '请先上传音频',
182    'toast.cleared': '曲库已清空',
183    'toast.deleted': '已删除《{title}》',
184    'toast.created': '《{title}》已创作完成',
185    'toast.playFailed': '这首播不了。换一首试试。',
186    'toast.copied': '已复制',
187    'toast.mock': '这是占位示例音频,真实作品音频稍后替换。',
188
189    'err.audio_transcode': '这段音频没能解码。支持 wav / flac / mp3 / opus,换一个文件试试。',
190    'err.no_speech_detected': '这段音频里没听到人声。换一段清晰的说话录音。',
191    'err.censor': '内容没有通过安全审核。调整描述或歌词后再试。',
192    'err.internal': '服务出了点问题。稍后再试一次。',
193    'err.unknown': '生成失败({stage})。稍后再试。',
194    'err.not_allowed': '接口鉴权失败。请联系我们。',
195    'err.request_params_invalid': '请求参数有问题:{message}',
196    'err.model_invalid': '这个账号还没有音乐模型的权限。',
197    'err.rate_limited': '请求太密集了,等一会儿再试。',
198    'err.service_unavailable': '服务暂时不可用,稍后再试。',
199    'err.network': '网络连接不上。检查网络后重试。',
200    'err.timeout': '等待超时。任务可能仍在后台运行。',
201    'err.offline': '网络断开了。已生成的作品还能听。',
202
203    'meta.instrumental': '器乐',
204  },
205
206  en: {
207    'app.title': 'StepAudio-3-Music · AI Music Generation',
208    'brand.name': 'StepAudio 3',
209    'brand.sub': 'Music',
210
211    'nav.home': 'Home',
212    'nav.listen': 'Listen',
213    'nav.create': 'Create',
214    'nav.library': 'Library',
215    'nav.contact': 'Contact',
216    'nav.arxiv': 'ArXiv',
217    'nav.api': 'API Docs',
218    'nav.apikey': 'API Setup',
219    'nav.collapse': 'Collapse',
220    'nav.expand': 'Expand',
221
222    /* ── API Key setup (visitors bring their own key, see config.js) ── */
223    'key.title': 'API Setup',
224    'key.promo': 'No key yet? Sign up on the StepFun platform to claim free API credits.',
225    'key.goPlatform': 'Go now',
226    'key.label': 'API Key',
227    'key.placeholder': 'Paste your API key',
228    'key.current': 'Currently set:',
229    'key.privacy': 'Your key is stored only in this browser. It is never uploaded to any server, and never committed to the repo.',
230    'key.show': 'Show key',
231    'key.hide': 'Hide key',
232    'key.save': 'Save & verify',
233    'key.clear': 'Clear',
234    'key.verifying': 'Verifying…',
235    'key.ok': 'Verified — you are ready to create.',
236    'key.saved': 'API key saved',
237    'key.savedThrottled': 'API key saved (API is rate-limited right now, try generating shortly)',
238    'key.cleared': 'API key cleared',
239    'key.err.key_empty': 'Enter your API key first.',
240    'key.err.key_invalid': 'That key is not valid — check that you copied all of it.',
241    'key.err.key_no_music': 'The key is valid, but this account lacks access to the music model (step-music).',
242    'key.err.key_timeout': 'Verification timed out. Check your connection and retry.',
243    'key.err.network': 'Could not reach the API. Check your connection and retry.',
244    'key.err.offline': 'You are offline. Reconnect and try again.',
245    'key.err.service_unavailable': 'Service is temporarily unavailable. Verify again later.',
246    'key.needTitle': 'No API key configured',
247    'key.needBody': 'Generating music needs your own StepFun API key. It takes about a minute to set up — the platform gives out free credits.',
248    'key.later': 'Later',
249    'key.goSetup': 'Set it up',
250
251    'home.placeholder': 'A rain-washed city at night. Breezy city pop, female lead, electric piano and vintage synths…',
252    'home.instrumental': 'Instrumental',
253    'home.dice': 'Random idea',
254    'home.create': 'Create',
255    'home.shuffle': 'Shuffle',
256    'home.featured': 'Featured',
257
258    'listen.title': 'Listen',
259    'listen.lead': 'Four capabilities, five examples each. Where audio goes in, you can hear the input before the output.',
260    'listen.in': 'In',
261    'listen.arrow': '→',
262    'sec.song': 'Song Generation',
263    'sec.song.desc': 'One line of style, optional lyrics, a full song with vocals.',
264    'sec.song.in': 'Text',
265    'sec.instrumental': 'Instrumental',
266    'sec.instrumental.desc': 'Music without vocals, for beds and scoring.',
267    'sec.instrumental.in': 'Text',
268    'sec.vocal2music': 'Vocal to Song',
269    'sec.vocal2music.desc': 'The melody follows your a cappella; the model writes the arrangement.',
270    'sec.vocal2music.in': 'A cappella + text',
271    'sec.cover': 'Song Cover',
272    'sec.cover.desc': 'Keep the reference melody, change the style and arrangement.',
273    'sec.cover.in': 'Song + text',
274    'sec.out.song': 'Full song',
275    'sec.out.instrumental': 'Instrumental',
276
277    'create.title': 'Create',
278    'create.tab.song': 'Song',
279    'create.tab.vocal2music': 'Vocal to Song',
280    'create.tab.cover': 'Song Cover',
281    'create.about.song': 'Write lyrics and a prompt, get a song of your own.',
282    'create.about.vocal2music': 'Upload an a cappella; lyrics and a prompt fill in the full arrangement.',
283    'create.about.cover': 'Upload the original and change its style.',
284    'create.title2': 'Song title',
285    'create.titlePlaceholder': 'Leave empty to auto-name',
286    'create.hint.vocal2music': 'Lyrics matching your uploaded vocal give better results.',
287    'create.hint.cover': 'Lyrics matching the original music give better results.',
288    'create.desc': 'Description',
289    'create.required': 'Required',
290    'create.optional': 'Optional',
291    'create.descPlaceholder': 'Style, mood, instruments, key…',
292    'create.lyrics': 'Lyrics',
293    'create.lyricsPlaceholder': '[Verse]\n\n[Chorus]',
294    'create.lyricsAuto': 'Leave empty and the model writes them',
295    'create.instrumental': 'Instrumental',
296    'create.instrumentalHint': 'Generate music without vocals',
297    'create.upload.vocal': 'A cappella',
298    'create.upload.vocalHint': 'Upload unaccompanied singing',
299    'create.upload.song': 'Reference song',
300    'create.upload.songHint': 'Upload a finished song',
301    'create.upload.formats': 'wav / flac / mp3 / opus',
302    'create.upload.replace': 'Choose another file',
303    'create.note.vocal2music': 'Lyrics must match what you sing in the upload.',
304    'create.note.cover': 'Lyrics must match the reference song.',
305    'create.advanced': 'Advanced',
306    'create.format': 'Output format',
307    'create.bitrate': 'Bit rate (kbps)',
308    'create.submit': 'Create',
309    'create.submitting': 'Submitting…',
310    'create.session': 'This session',
311    'create.sessionEmpty': 'What you create in this session shows up here.',
312    'create.viewAll': 'See all tracks',
313    'create.quotaLeft': '{n} left today',
314    'create.quotaOut': 'Out of runs for today. Come back tomorrow.',
315    'create.noKey': 'No API key yet — hit Create and follow the prompt.',
316
317    'status.uploading': 'Uploading',
318    'status.pending': 'Queued',
319    'status.running': 'Generating',
320    'status.success': 'Done',
321    'status.failed': 'Failed',
322    'status.elapsed': '{time} elapsed',
323    'status.hint': 'Usually 1–3 minutes. You can browse other pages; the job keeps running.',
324    'status.retry': 'Retry',
325    'status.cancel': 'Cancel',
326
327    'confirm.delete': 'Delete track',
328    'confirm.deleteBody': 'This cannot be undone.',
329    'confirm.deleteOk': 'Delete',
330    'confirm.cancel': 'Cancel',
331    'confirm.clear': 'Clear library',
332    'confirm.clearBody': 'All tracks will be deleted. This cannot be undone.',
333    'player.delete': 'Delete',
334    'library.title': 'Library',
335    'library.lead': 'Your tracks are stored in this browser on this device.',
336    'library.empty': 'Nothing here yet',
337    'library.emptyHint': 'Create your first track.',
338    'library.emptyCta': 'Start creating',
339    'library.all': 'All',
340    'library.clear': 'Clear library',
341    'library.clearConfirm': 'Delete every track? This cannot be undone.',
342    'library.count': '{n} tracks',
343
344    'player.play': 'Play',
345    'player.pause': 'Pause',
346    'player.prev': 'Previous',
347    'player.next': 'Next',
348    'player.like': 'Like',
349    'player.unlike': 'Remove like',
350    'player.download': 'Download',
351    'player.repeat.off': 'No repeat',
352    'player.repeat.all': 'Repeat all',
353    'player.repeat.one': 'Repeat one',
354    'player.volume': 'Volume',
355    'player.mute': 'Mute',
356    'player.unmute': 'Unmute',
357    'player.expand': 'Expand',
358    'player.collapse': 'Collapse',
359    'player.close': 'Close',
360    'player.progress': 'Seek',
361
362    'np.lyrics': 'Lyrics',
363    'np.noLyrics': 'Instrumental — no lyrics.',
364    'np.caption': 'Description',
365    'np.input': 'Input audio',
366    'np.noLyricsGiven': 'No lyrics for this track.',
367    'np.input.vocal_audio': 'A cappella',
368    'np.input.song_audio': 'Reference song',
369
370    'toast.liked': 'Added to likes',
371    'toast.unliked': 'Removed from likes',
372    'toast.downloaded': 'Download started',
373    'toast.recipe': 'Idea filled in — edit as you like',
374    'toast.noDesc': 'Write a description first',
375    'toast.noAudio': 'Upload an audio file first',
376    'toast.cleared': 'Library cleared',
377    'toast.deleted': 'Deleted “{title}”',
378    'toast.created': '“{title}” is ready',
379    'toast.playFailed': "That one won't play. Try another.",
380    'toast.copied': 'Copied',
381    'toast.mock': 'Placeholder audio — real tracks land later.',
382
383    'err.audio_transcode': "Couldn't decode that audio. Use wav, flac, mp3, or opus.",
384    'err.no_speech_detected': 'No voice detected. Try a clearer speech recording.',
385    'err.censor': "Content didn't pass review. Adjust the description or lyrics.",
386    'err.internal': 'Something went wrong on our side. Try again shortly.',
387    'err.unknown': 'Generation failed ({stage}). Try again shortly.',
388    'err.not_allowed': 'API authentication failed. Please contact us.',
389    'err.request_params_invalid': 'Invalid request: {message}',
390    'err.model_invalid': "This account doesn't have access to the music model yet.",
391    'err.rate_limited': 'Too many requests. Try again in a moment.',
392    'err.service_unavailable': 'Service unavailable. Try again shortly.',
393    'err.network': "Can't reach the network. Check your connection and retry.",
394    'err.timeout': 'Timed out waiting. The job may still be running.',
395    'err.offline': 'You are offline. Tracks you already have still play.',
396
397    'meta.instrumental': 'Instrumental',
398  },
399};
400
401const LS_KEY = 'sa3m.lang';
402let lang = DEFAULT_LANG;
403const listeners = new Set();
404
405try {
406  const saved = localStorage.getItem(LS_KEY);
407  if (saved === 'zh' || saved === 'en') lang = saved;
408} catch { /* 隐私模式下 localStorage 会抛错,忽略 */ }
409
410export const getLang = () => lang;
411
412export function setLang(next) {
413  if (next !== 'zh' && next !== 'en') return;
414  if (next === lang) return;
415  lang = next;
416  try { localStorage.setItem(LS_KEY, lang); } catch {}
417  document.documentElement.lang = lang === 'zh' ? 'zh-CN' : 'en';
418  listeners.forEach(fn => fn(lang));
419}
420
421export const onLangChange = fn => { listeners.add(fn); return () => listeners.delete(fn); };
422
423export function t(key, vars) {
424  let s = DICT[lang][key] ?? DICT[DEFAULT_LANG][key] ?? key;
425  if (vars) for (const k in vars) s = s.replaceAll(`{${k}}`, vars[k]);
426  return s;
427}
428
429/** 取曲目的本地化字段:title/title_en、tags/tags_en、caption/caption_en */
430export function locField(obj, base) {
431  if (!obj) return '';
432  return (lang === 'en' ? (obj[base + '_en'] ?? obj[base]) : obj[base]) ?? '';
433}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.