Næste version
This commit is contained in:
57
linedance-app/translations/__init__.py
Normal file
57
linedance-app/translations/__init__.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""
|
||||
translations/__init__.py — Central oversættelsesfunktion.
|
||||
|
||||
Brug:
|
||||
from translations import _
|
||||
btn = QPushButton(_("btn.start_event"))
|
||||
lbl = QLabel(_("level.beginner"))
|
||||
|
||||
Fallback: hvis nøglen ikke findes returneres nøglen selv.
|
||||
"""
|
||||
|
||||
_current: dict[str, str] = {}
|
||||
_current_lang: str = "da"
|
||||
|
||||
|
||||
def load_language(lang: str = "da"):
|
||||
"""Indlæs sprogfil. Kaldes ved opstart og ved sprogskift i indstillinger."""
|
||||
global _current, _current_lang
|
||||
_current_lang = lang
|
||||
try:
|
||||
if lang == "en":
|
||||
from translations.en import STRINGS
|
||||
else:
|
||||
from translations.da import STRINGS
|
||||
_current = STRINGS
|
||||
except ImportError:
|
||||
from translations.da import STRINGS
|
||||
_current = STRINGS
|
||||
|
||||
|
||||
def _(key: str, **kwargs) -> str:
|
||||
"""Oversæt en nøgle. Fallback = nøglen selv hvis ikke fundet."""
|
||||
text = _current.get(key, key)
|
||||
return text.format(**kwargs) if kwargs else text
|
||||
|
||||
|
||||
def current_lang() -> str:
|
||||
return _current_lang
|
||||
|
||||
|
||||
def translate_level(level_name: str | None) -> str:
|
||||
"""Oversæt et niveau-navn fra API/DB canonical navn til valgt sprog."""
|
||||
if not level_name:
|
||||
return _("level.none")
|
||||
key = f"level.{level_name.lower().replace(' ', '_').replace('ø', 'o').replace('æ', 'ae').replace('å', 'aa')}"
|
||||
result = _current.get(key)
|
||||
if result:
|
||||
return result
|
||||
# Fallback: prøv direkte match
|
||||
for k, v in _current.items():
|
||||
if k.startswith("level.") and v.lower() == level_name.lower():
|
||||
return v
|
||||
return level_name # helt rå fallback
|
||||
|
||||
|
||||
# Indlæs dansk som standard ved import
|
||||
load_language("da")
|
||||
201
linedance-app/translations/da.py
Normal file
201
linedance-app/translations/da.py
Normal file
@@ -0,0 +1,201 @@
|
||||
"""Dansk oversættelse — standardsprog."""
|
||||
|
||||
STRINGS = {
|
||||
# App
|
||||
"app.title": "LineDance Player",
|
||||
"app.ready": "Klar",
|
||||
"app.no_song": "— Ingen sang indlæst —",
|
||||
"app.playlist_done": "— Danseliste afsluttet —",
|
||||
"app.no_dance_tagged": "ingen dans tagget",
|
||||
|
||||
# Menu
|
||||
"menu.file": "Filer",
|
||||
"menu.go_online": "Gå online...",
|
||||
"menu.go_offline": "Gå offline",
|
||||
"menu.settings": "Indstillinger...",
|
||||
"menu.quit": "Afslut",
|
||||
|
||||
# Bibliotek
|
||||
"library.title": "BIBLIOTEK",
|
||||
"library.search": "Søg i titel, artist, album, dans...",
|
||||
"library.songs": "{count} sange",
|
||||
"library.song": "{count} sang",
|
||||
"library.results": "{count} resultater for \"{query}\"",
|
||||
"library.result": "{count} resultat for \"{query}\"",
|
||||
"library.btn_bpm": "♩ BPM alle",
|
||||
"library.btn_manage": "⚙ Mapper",
|
||||
"library.bpm_scanning": "♩ {done}/{total}...",
|
||||
"library.bpm_all_done": "♩ Alle har BPM",
|
||||
"library.missing": "⚠ ",
|
||||
"library.no_dance": "ingen dans tagget",
|
||||
|
||||
# Mapper dialog
|
||||
"folders.title": "Administrer musikbiblioteker",
|
||||
"folders.active": "Aktive musikbiblioteker:",
|
||||
"folders.note": "Når du fjerner et bibliotek, slettes det fra overvågningen.\nSangene forbliver i databasen men markeres som manglende (⚠).",
|
||||
"folders.btn_add": "+ Tilføj mappe",
|
||||
"folders.btn_remove": "✕ Fjern valgt",
|
||||
"folders.btn_scan": "⟳ Scan alle",
|
||||
"folders.btn_close": "Luk",
|
||||
"folders.never_scanned": "aldrig",
|
||||
"folders.not_found": " ⚠ mappe ikke fundet",
|
||||
"folders.songs_count": "{count} sange · senest scannet: {date}",
|
||||
"folders.confirm_remove": "Fjern overvågningen af:\n{path}\n\nSange i biblioteket forbliver i databasen men markeres som manglende.",
|
||||
|
||||
# Danseliste
|
||||
"playlist.title": "DANSELISTE",
|
||||
"playlist.new_title": "DANSELISTE — NY",
|
||||
"playlist.btn_new": "✚ Ny",
|
||||
"playlist.btn_save": "💾 Gem som...",
|
||||
"playlist.btn_load": "📂 Hent...",
|
||||
"playlist.btn_start": "▶ START EVENT",
|
||||
"playlist.progress": "{played} / {total} afspillet",
|
||||
"playlist.not_saved": "● ikke gemt",
|
||||
"playlist.saved": "✓ gemt",
|
||||
"playlist.save_error": "⚠ gemfejl",
|
||||
"playlist.restored": "✓ gendannet",
|
||||
"playlist.saved_as": "✓ gemt som \"{name}\"",
|
||||
"playlist.name_prompt": "Navn på danselisten:",
|
||||
"playlist.name_dialog": "Gem danseliste",
|
||||
"playlist.load_dialog": "Hent danseliste",
|
||||
"playlist.load_choose": "Vælg en liste:",
|
||||
"playlist.empty": "Danselisten er tom.",
|
||||
"playlist.no_lists": "Ingen gemte danselister fundet.",
|
||||
"playlist.confirm_new": "Ryd den aktuelle liste og start forfra?",
|
||||
"playlist.confirm_event": "Dette nulstiller alle statusser i danselisten.\nFortsæt?",
|
||||
"playlist.ready": "Klar: {title} — tryk ▶ for at starte",
|
||||
"playlist.done": "Danselisten er afsluttet",
|
||||
"playlist.event_ready": "Event klar: {title} — tryk ▶ for at starte",
|
||||
"playlist.added": "Tilføjet til danseliste: {title}",
|
||||
|
||||
# Kontekstmenu danseliste
|
||||
"playlist.ctx_play": "▶ Afspil denne",
|
||||
"playlist.ctx_skip": "— Spring over",
|
||||
"playlist.ctx_unplay": "↺ Sæt til ikke afspillet",
|
||||
"playlist.ctx_played": "✓ Sæt til afspillet",
|
||||
"playlist.ctx_remove": "✕ Fjern fra liste",
|
||||
|
||||
# Kontekstmenu bibliotek
|
||||
"library.ctx_add": "Tilføj til danseliste",
|
||||
"library.ctx_play": "Afspil",
|
||||
"library.ctx_tags": "✎ Rediger dans-tags...",
|
||||
"library.ctx_bpm": "♩ Analysér BPM",
|
||||
"library.ctx_send": "Send til",
|
||||
"library.ctx_mail": "✉ Send som mail",
|
||||
"library.btn_danse": "Danse",
|
||||
|
||||
# Afspiller
|
||||
"player.no_song": "Ingen sang indlæst",
|
||||
"player.loaded": "Indlæst: {title}",
|
||||
"player.vol": "VOL",
|
||||
"player.demo_btn": "▶\n{sec} SEK",
|
||||
"player.event_resumed": "Event genoptaget ved: {title} — tryk ▶ for at fortsætte",
|
||||
|
||||
# Transport-knapper (tooltips)
|
||||
"player.btn_prev": "Forrige sang",
|
||||
"player.btn_play": "Afspil / Pause",
|
||||
"player.btn_stop": "Stop",
|
||||
"player.btn_next": "Næste sang",
|
||||
"player.btn_demo": "Afspil forspil",
|
||||
|
||||
# Indstillinger
|
||||
"settings.title": "Indstillinger",
|
||||
"settings.tab_appearance": "🎨 Udseende",
|
||||
"settings.tab_playback": "▶ Afspilning",
|
||||
"settings.tab_mail": "✉ Mail",
|
||||
"settings.tab_online": "🌐 Online",
|
||||
"settings.tab_language": "🌍 Sprog",
|
||||
"settings.btn_save": "💾 Gem indstillinger",
|
||||
"settings.btn_cancel": "Annuller",
|
||||
"settings.dark_theme": "Start med mørkt tema",
|
||||
"settings.theme_note": "Du kan altid skifte tema mens programmet kører via topbar-knappen.",
|
||||
"settings.demo_group": "Forspil (▶ N SEK knappen)",
|
||||
"settings.demo_length": "Forspil-længde:",
|
||||
"settings.demo_fade": "Fade-ud:",
|
||||
"settings.demo_suffix": " sekunder",
|
||||
"settings.fade_suffix": " sekunder (0 = ingen fade)",
|
||||
"settings.demo_note": "Forspillet afspiller begyndelsen af sangen.\nFade-ud tilføjes oven i forspillets længde.",
|
||||
"settings.mail_group": "Mailklient",
|
||||
"settings.mail_label": "Klient:",
|
||||
"settings.mail_path": "Sti:",
|
||||
"settings.mail_auto": "Auto-detekter (Thunderbird → Outlook → mailto:)",
|
||||
"settings.mail_tb": "Thunderbird",
|
||||
"settings.mail_ol": "Outlook (Windows)",
|
||||
"settings.mail_custom": "Brugerdefineret sti",
|
||||
"settings.mail_mailto": "Kun mailto: (ingen vedhæftning)",
|
||||
"settings.mail_note": "Med Thunderbird og Outlook åbnes et nyt compose-vindue med filen vedhæftet.",
|
||||
"settings.online_group": "Automatisk login ved opstart",
|
||||
"settings.auto_login": "Log automatisk ind når programmet starter",
|
||||
"settings.username": "Brugernavn:",
|
||||
"settings.password": "Kodeord:",
|
||||
"settings.password_warn": "⚠ Kodeordet gemmes lokalt på denne computer.\nBrug kun dette på en personlig maskine.",
|
||||
"settings.lang_group": "Sprog",
|
||||
"settings.lang_label": "Programsprog:",
|
||||
"settings.lang_note": "Sproget anvendes næste gang programmet startes.",
|
||||
"settings.saved": "Indstillinger gemt",
|
||||
|
||||
# Tag-editor
|
||||
"tags.title": "Rediger tags — {title}",
|
||||
"tags.can_write": "✓ Danse skrives til filen",
|
||||
"tags.cant_write": "⚠ Dette format understøtter ikke fil-skrivning",
|
||||
"tags.hint": "Skriv dansenavn — forslag vises som 'Navn / Niveau'. Vælg fra listen for at få niveau automatisk.",
|
||||
"tags.dances": "Danse",
|
||||
"tags.alts": "Alternativ-danse",
|
||||
"tags.btn_add": "+ Tilføj",
|
||||
"tags.btn_save": "💾 Gem tags",
|
||||
"tags.btn_cancel": "Annuller",
|
||||
"tags.new_dance": "Ny dans (f.eks. Cowboy Cha Cha)...",
|
||||
"tags.new_alt": "Alternativ dans...",
|
||||
"tags.note": "note...",
|
||||
"tags.warn_file": "Gemt i database, men kunne ikke skrive til filen.",
|
||||
"tags.error": "Kunne ikke gemme: {error}",
|
||||
"tags.no_level": "— intet niveau —",
|
||||
|
||||
# Niveauer
|
||||
"level.none": "— intet niveau —",
|
||||
"level.beginner": "Begynder",
|
||||
"level.let_ovet": "Let øvet",
|
||||
"level.easy": "Let øvet",
|
||||
"level.ovet": "Øvet",
|
||||
"level.intermediate": "Øvet",
|
||||
"level.erfaren": "Erfaren",
|
||||
"level.experienced": "Erfaren",
|
||||
"level.ekspert": "Ekspert",
|
||||
"level.expert": "Ekspert",
|
||||
|
||||
# Online / login
|
||||
"online.logging_in": "Logger ind som {username}...",
|
||||
"online.logged_in": "Online som {username}",
|
||||
"online.auto_login_fail": "Auto-login fejlede — kør Filer → Gå online manuelt",
|
||||
"online.logged_out": "Offline",
|
||||
"online.syncing": "Synkroniserer dans-data...",
|
||||
"online.synced": "Synkroniseret {levels} niveauer og {names} dans-navne",
|
||||
|
||||
# Scanning
|
||||
"scan.preparing": "Starter scanning af biblioteker...",
|
||||
"scan.scanning": "Scanner: {name}...",
|
||||
"scan.scanning_count": "Scanner: {name} ({count} filer)...",
|
||||
"scan.done": "Scan færdig — {count} filer gennemgået",
|
||||
"scan.error": "Scan fejl: {error}",
|
||||
"scan.folder_missing": "⚠ Mappe ikke fundet: {path}",
|
||||
|
||||
# Fejl
|
||||
"error.title": "Fejl",
|
||||
"error.db_init": "Database fejl: {error}",
|
||||
"error.folder_remove": "Kunne ikke fjerne: {error}",
|
||||
"error.save_tags": "Kunne ikke gemme tags: {error}",
|
||||
|
||||
# Mail
|
||||
"mail.thunderbird_ok": "Thunderbird åbnet med {filename} vedh.",
|
||||
"mail.outlook_ok": "Outlook åbnet med {filename} vedh.",
|
||||
"mail.fallback": "Ingen kendt mailklient fundet — åbnet mailto: (uden vedhæftning)",
|
||||
"mail.file_missing": "Filen blev ikke fundet — kan ikke sende mail",
|
||||
|
||||
# Generelt
|
||||
"btn.ok": "OK",
|
||||
"btn.cancel": "Annuller",
|
||||
"btn.close": "Luk",
|
||||
"btn.yes": "Ja",
|
||||
"btn.no": "Nej",
|
||||
"dialog.confirm": "Bekræft",
|
||||
}
|
||||
201
linedance-app/translations/en.py
Normal file
201
linedance-app/translations/en.py
Normal file
@@ -0,0 +1,201 @@
|
||||
"""English translation."""
|
||||
|
||||
STRINGS = {
|
||||
# App
|
||||
"app.title": "LineDance Player",
|
||||
"app.ready": "Ready",
|
||||
"app.no_song": "— No song loaded —",
|
||||
"app.playlist_done": "— Playlist finished —",
|
||||
"app.no_dance_tagged": "no dance tagged",
|
||||
|
||||
# Menu
|
||||
"menu.file": "File",
|
||||
"menu.go_online": "Go online...",
|
||||
"menu.go_offline": "Go offline",
|
||||
"menu.settings": "Settings...",
|
||||
"menu.quit": "Quit",
|
||||
|
||||
# Library
|
||||
"library.title": "LIBRARY",
|
||||
"library.search": "Search title, artist, album, dance...",
|
||||
"library.songs": "{count} songs",
|
||||
"library.song": "{count} song",
|
||||
"library.results": "{count} results for \"{query}\"",
|
||||
"library.result": "{count} result for \"{query}\"",
|
||||
"library.btn_bpm": "♩ BPM all",
|
||||
"library.btn_manage": "⚙ Folders",
|
||||
"library.bpm_scanning": "♩ {done}/{total}...",
|
||||
"library.bpm_all_done": "♩ All have BPM",
|
||||
"library.missing": "⚠ ",
|
||||
"library.no_dance": "no dance tagged",
|
||||
|
||||
# Folders dialog
|
||||
"folders.title": "Manage music libraries",
|
||||
"folders.active": "Active music libraries:",
|
||||
"folders.note": "When you remove a library, it is removed from monitoring.\nSongs remain in the database but are marked as missing (⚠).",
|
||||
"folders.btn_add": "+ Add folder",
|
||||
"folders.btn_remove": "✕ Remove selected",
|
||||
"folders.btn_scan": "⟳ Scan all",
|
||||
"folders.btn_close": "Close",
|
||||
"folders.never_scanned": "never",
|
||||
"folders.not_found": " ⚠ folder not found",
|
||||
"folders.songs_count": "{count} songs · last scanned: {date}",
|
||||
"folders.confirm_remove": "Remove monitoring of:\n{path}\n\nSongs remain in the database but will be marked as missing.",
|
||||
|
||||
# Playlist
|
||||
"playlist.title": "PLAYLIST",
|
||||
"playlist.new_title": "PLAYLIST — NEW",
|
||||
"playlist.btn_new": "✚ New",
|
||||
"playlist.btn_save": "💾 Save as...",
|
||||
"playlist.btn_load": "📂 Load...",
|
||||
"playlist.btn_start": "▶ START EVENT",
|
||||
"playlist.progress": "{played} / {total} played",
|
||||
"playlist.not_saved": "● unsaved",
|
||||
"playlist.saved": "✓ saved",
|
||||
"playlist.save_error": "⚠ save error",
|
||||
"playlist.restored": "✓ restored",
|
||||
"playlist.saved_as": "✓ saved as \"{name}\"",
|
||||
"playlist.name_prompt": "Playlist name:",
|
||||
"playlist.name_dialog": "Save playlist",
|
||||
"playlist.load_dialog": "Load playlist",
|
||||
"playlist.load_choose": "Choose a playlist:",
|
||||
"playlist.empty": "The playlist is empty.",
|
||||
"playlist.no_lists": "No saved playlists found.",
|
||||
"playlist.confirm_new": "Clear the current playlist and start over?",
|
||||
"playlist.confirm_event": "This will reset all statuses in the playlist.\nContinue?",
|
||||
"playlist.ready": "Ready: {title} — press ▶ to start",
|
||||
"playlist.done": "Playlist finished",
|
||||
"playlist.event_ready": "Event ready: {title} — press ▶ to start",
|
||||
"playlist.added": "Added to playlist: {title}",
|
||||
|
||||
# Playlist context menu
|
||||
"playlist.ctx_play": "▶ Play this",
|
||||
"playlist.ctx_skip": "— Skip",
|
||||
"playlist.ctx_unplay": "↺ Mark as not played",
|
||||
"playlist.ctx_played": "✓ Mark as played",
|
||||
"playlist.ctx_remove": "✕ Remove from playlist",
|
||||
|
||||
# Library context menu
|
||||
"library.ctx_add": "Add to playlist",
|
||||
"library.ctx_play": "Play",
|
||||
"library.ctx_tags": "✎ Edit dance tags...",
|
||||
"library.ctx_bpm": "♩ Analyse BPM",
|
||||
"library.ctx_send": "Send to",
|
||||
"library.ctx_mail": "✉ Send by email",
|
||||
"library.btn_danse": "Dances",
|
||||
|
||||
# Player
|
||||
"player.no_song": "No song loaded",
|
||||
"player.loaded": "Loaded: {title}",
|
||||
"player.vol": "VOL",
|
||||
"player.demo_btn": "▶\n{sec} SEC",
|
||||
"player.event_resumed": "Event resumed at: {title} — press ▶ to continue",
|
||||
|
||||
# Transport tooltips
|
||||
"player.btn_prev": "Previous song",
|
||||
"player.btn_play": "Play / Pause",
|
||||
"player.btn_stop": "Stop",
|
||||
"player.btn_next": "Next song",
|
||||
"player.btn_demo": "Play preview",
|
||||
|
||||
# Settings
|
||||
"settings.title": "Settings",
|
||||
"settings.tab_appearance": "🎨 Appearance",
|
||||
"settings.tab_playback": "▶ Playback",
|
||||
"settings.tab_mail": "✉ Mail",
|
||||
"settings.tab_online": "🌐 Online",
|
||||
"settings.tab_language": "🌍 Language",
|
||||
"settings.btn_save": "💾 Save settings",
|
||||
"settings.btn_cancel": "Cancel",
|
||||
"settings.dark_theme": "Start with dark theme",
|
||||
"settings.theme_note": "You can always switch theme while the program is running.",
|
||||
"settings.demo_group": "Preview (▶ N SEC button)",
|
||||
"settings.demo_length": "Preview length:",
|
||||
"settings.demo_fade": "Fade-out:",
|
||||
"settings.demo_suffix": " seconds",
|
||||
"settings.fade_suffix": " seconds (0 = no fade)",
|
||||
"settings.demo_note": "The preview plays the beginning of the song.\nFade-out is added on top of the preview length.",
|
||||
"settings.mail_group": "Mail client",
|
||||
"settings.mail_label": "Client:",
|
||||
"settings.mail_path": "Path:",
|
||||
"settings.mail_auto": "Auto-detect (Thunderbird → Outlook → mailto:)",
|
||||
"settings.mail_tb": "Thunderbird",
|
||||
"settings.mail_ol": "Outlook (Windows)",
|
||||
"settings.mail_custom": "Custom path",
|
||||
"settings.mail_mailto": "mailto: only (no attachment)",
|
||||
"settings.mail_note": "With Thunderbird and Outlook a new compose window opens with the file attached.",
|
||||
"settings.online_group": "Automatic login at startup",
|
||||
"settings.auto_login": "Log in automatically when the program starts",
|
||||
"settings.username": "Username:",
|
||||
"settings.password": "Password:",
|
||||
"settings.password_warn": "⚠ The password is stored locally on this computer.\nOnly use this on a personal machine.",
|
||||
"settings.lang_group": "Language",
|
||||
"settings.lang_label": "Interface language:",
|
||||
"settings.lang_note": "The language will be applied next time the program starts.",
|
||||
"settings.saved": "Settings saved",
|
||||
|
||||
# Tag editor
|
||||
"tags.title": "Edit tags — {title}",
|
||||
"tags.can_write": "✓ Dances are written to the file",
|
||||
"tags.cant_write": "⚠ This format does not support file writing",
|
||||
"tags.hint": "Type a dance name — suggestions show as 'Name / Level'. Select from list to set level automatically.",
|
||||
"tags.dances": "Dances",
|
||||
"tags.alts": "Alternative dances",
|
||||
"tags.btn_add": "+ Add",
|
||||
"tags.btn_save": "💾 Save tags",
|
||||
"tags.btn_cancel": "Cancel",
|
||||
"tags.new_dance": "New dance (e.g. Cowboy Cha Cha)...",
|
||||
"tags.new_alt": "Alternative dance...",
|
||||
"tags.note": "note...",
|
||||
"tags.warn_file": "Saved to database, but could not write to file.",
|
||||
"tags.error": "Could not save: {error}",
|
||||
"tags.no_level": "— no level —",
|
||||
|
||||
# Levels
|
||||
"level.none": "— no level —",
|
||||
"level.beginner": "Beginner",
|
||||
"level.let_ovet": "Easy",
|
||||
"level.easy": "Easy",
|
||||
"level.ovet": "Intermediate",
|
||||
"level.intermediate": "Intermediate",
|
||||
"level.erfaren": "Experienced",
|
||||
"level.experienced": "Experienced",
|
||||
"level.ekspert": "Expert",
|
||||
"level.expert": "Expert",
|
||||
|
||||
# Online / login
|
||||
"online.logging_in": "Logging in as {username}...",
|
||||
"online.logged_in": "Online as {username}",
|
||||
"online.auto_login_fail": "Auto-login failed — use File → Go online manually",
|
||||
"online.logged_out": "Offline",
|
||||
"online.syncing": "Syncing dance data...",
|
||||
"online.synced": "Synced {levels} levels and {names} dance names",
|
||||
|
||||
# Scanning
|
||||
"scan.preparing": "Starting library scan...",
|
||||
"scan.scanning": "Scanning: {name}...",
|
||||
"scan.scanning_count": "Scanning: {name} ({count} files)...",
|
||||
"scan.done": "Scan complete — {count} files processed",
|
||||
"scan.error": "Scan error: {error}",
|
||||
"scan.folder_missing": "⚠ Folder not found: {path}",
|
||||
|
||||
# Errors
|
||||
"error.title": "Error",
|
||||
"error.db_init": "Database error: {error}",
|
||||
"error.folder_remove": "Could not remove: {error}",
|
||||
"error.save_tags": "Could not save tags: {error}",
|
||||
|
||||
# Mail
|
||||
"mail.thunderbird_ok": "Thunderbird opened with {filename} attached.",
|
||||
"mail.outlook_ok": "Outlook opened with {filename} attached.",
|
||||
"mail.fallback": "No known mail client found — opened mailto: (no attachment)",
|
||||
"mail.file_missing": "File not found — cannot send mail",
|
||||
|
||||
# General
|
||||
"btn.ok": "OK",
|
||||
"btn.cancel": "Cancel",
|
||||
"btn.close": "Close",
|
||||
"btn.yes": "Yes",
|
||||
"btn.no": "No",
|
||||
"dialog.confirm": "Confirm",
|
||||
}
|
||||
Reference in New Issue
Block a user