본문으로 건너뛰기
cccskills
무료GitHub에 공개

i18n

Add, change, or translate user-facing text in the Lyrion Dashboard, which ships bilingual FR/EN. Use this whenever a task introduces a new visible string (a label, tooltip, aria-label, empty state, stat name), changes wording, or touches the README or a `docs/` page — so every string lands in both languages and the EN/FR documentation pairs stay in sync. Covers `i18n.py`, how templates and JS consume translations, and the parity rule.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(1)

  • SKILL.md4.5 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Internationalization (FR/EN)

The whole UI is bilingual. There is one source of truth for UI strings — i18n.py — and two parallel READMEs. The cardinal rule: a string never exists in only one language. Adding an English label without its French counterpart (or vice-versa) is the bug this skill exists to prevent.

How it works

i18n.py holds a TRANSLATIONS dict with a fr and an en sub-dict sharing the same keys. Language is chosen per request from the browser's Accept-Language header, defaulting to English:

SUPPORTED = ("fr", "en")
DEFAULT_LANG = "en"

def pick_lang(accept_languages):
    return accept_languages.best_match(SUPPORTED) or DEFAULT_LANG

The route resolves the language and hands the entire chosen dict to the template as t, which is also serialized to JS so client-side strings share the same source:

lang = pick_lang(request.accept_languages)
return render_template("nowplaying.html", lang=lang, t=TRANSLATIONS[lang], ...)

Adding or changing a UI string

  1. Add the key to both fr and en in TRANSLATIONS, under the matching comment section (# Now playing, # Stats, ...). Keep the two sub-dicts in the same order so a missing key is visible at a glance.
  2. Use the key in the template via t, e.g. {{ t.stats_title }} or aria-label="{{ t.choose_player }}". Many existing strings are tooltips / aria-labels — user-facing text in attributes counts too.
  3. For client-side text, read it from the serialized t in static/nowplaying.js rather than hardcoding a literal — that's why the whole dict is exposed.
  4. Never hardcode a display string in a template or JS. If it's visible to a user, it's a translation key.

Keys are stable identifiers, not English text — snake_case describing the role (retry_lyrics, empty_state), so the English wording can change without renaming the key.

The parity test

tests/test_i18n.py turns the cardinal rule into a gate: fr and en must hold the same keys, no string may be blank, every I18N.key in static/*.js and every t.key in templates/*.html must be translated in both languages, and no key may survive with nothing reading it. Without it a missing key is silent — Jinja renders it as an empty string, and the JS hands undefined to a DOM property, so the tooltip reads the literal "undefined". The unused-key half is only exhaustive while access stays static: a computed I18N[name] would have to be taught to referenced_keys().

Documentation parity

Every documentation page exists twice, linked to its counterpart at the top:

  • README.md (EN, primary) / README.fr.md (FR) — the landing page: features, demo gallery, install, security.
  • docs/configuration.md, docs/logs.md, docs/endpoints.md, docs/scripts.md and their .fr.md counterparts — the detail the README links to.

Any change to one — a new feature bullet, a changed requirement, a restructured section — must be mirrored in the other in the same place. They should differ only in language, never in content or structure. When you edit one, edit the other in the same change.

android/README.md is deliberately English-only: it is contributor documentation (Gradle build, signing, CI, F-Droid packaging), and what a French user actually reads about the app is translated elsewhere — the READMEs, the UI, and the store listing under fastlane/metadata/android/. Every link to it from the FR README carries an "(en anglais)" flag — there are three, in the features list, the install section and the documentation list. Don't create a .fr.md for it; do keep that flag if the link moves.

Checklist

  • New UI string → key added to both fr and en in i18n.py.
  • Keys are snake_case role names, present in both sub-dicts in the same order.
  • Template/JS reads the string through t, nothing hardcoded.
  • python -m unittest tests.test_i18n green — parity, every key the page reads translated, no orphan key.
  • README or docs/ page edited? Its counterpart in the other language got the same edit.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

add-route

무료

Add or modify a Flask endpoint in the Lyrion Dashboard. Use this whenever a task adds a new URL/route, a JSON API endpoint, or a page — anything that registers a handler in `routes/`. Covers the repo's route → service → test layering, input validation, caching headers, security headers, i18n wiring, and the exact test pattern, so a new endpoint matches how `routes/` already works instead of reinventing the structure.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

werdeil/lyrion-dashboard32026년 10월 20일 업데이트

android

무료

Work on the Android app — the thin WebView wrapper in `android/`. Use this whenever a task touches the Kotlin sources, the Gradle build, the WebView shell, the native settings screen, LMS server auto-discovery, the JS↔native bridge, app strings/i18n, or the Android CI/lint. Covers the "shell only, UI lives on the web" principle, the debug/release signing split, the static versioning F-Droid needs, and the min/target SDKs, so changes fit the wrapper.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

werdeil/lyrion-dashboard32026년 10월 20일 업데이트

covers

무료

Work on album artwork — reading an image's dimensions, and embedding a folder's cover file into the tags of its tracks. Use this whenever a task touches `services/artwork.py`, the cover half of `services/tags.py`, or `scripts/embed_covers.py` / `embed_covers_cron.sh`. Covers why Lyrion shows the embedded artwork and never the folder file, how covers are compared, why images are never re-encoded, and what embedding costs in rewritten files.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

werdeil/lyrion-dashboard32026년 10월 20일 업데이트

database

무료

Read data from Lyrion's SQLite databases — library stats, stored lyrics, album covers, recent plays. Use this whenever a task queries `library.db` or `persist.db`, adds or changes a statistic, or touches `services/database.py`. Covers the read-only connection model (RO open + `ATTACH persist.db`), the key tables, the `play_counts` view over the Alternative Play Count plugin, the single-flight stats cache, and why the app must never write to these DBs. Reach for it before writing any SQL against the Lyrion databases.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

werdeil/lyrion-dashboard32026년 10월 20일 업데이트

frontend

무료

Work on the dashboard's frontend — the vanilla JS/CSS page with no framework or bundler. Use this whenever a task touches `static/nowplaying.js`, `static/style.css`, the Jinja templates (`templates/nowplaying.html`, `_icons.html`), the accent-color tinting, the karaoke lyrics sync, the now-playing poll, or the empty-state mosaic / recent-plays pile. Covers how the page is wired, how it reads i18n and data from the server, the ESLint gate, and the Android bridge, so changes match the existing patterns.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

werdeil/lyrion-dashboard32026년 10월 20일 업데이트

lyrics

무료

Work on lyrics — the web fallback (LRCLIB, Musixmatch, NetEase, Genius), the in-memory cache, verification, and embedding lyrics into audio file tags. Use this whenever a task touches `services/lyrics.py`, `services/tags.py`, the `/lyrics.json` route, or `scripts/embed_lyrics.py` / `embed_lyrics_cron.sh` — adding or fixing a provider, changing caching/verification, or the batch tagger. Covers the provider contract, the synced-vs-plain rule, the read-only cache, and why writes only ever store plain text.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

werdeil/lyrion-dashboard32026년 10월 20일 업데이트

werdeil의 스킬 모두 보기

이 스킬의 문제 신고