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.