Files
keydr/locales/en.yml
Tyler Hallada 6d5de33f55 Internationalize UI text w/ german as first second lang
Adds rust-i18n and refactors all of the text copy in the app to use the
translation function so that the UI language can be dynamically updated
in the settings.
2026-03-17 04:29:25 +00:00

458 lines
17 KiB
YAML

# Main menu
menu:
subtitle: 'Terminal Typing Tutor'
adaptive_drill: 'Adaptive Drill'
adaptive_drill_desc: 'Phonetic words with adaptive letter unlocking'
code_drill: 'Code Drill'
code_drill_desc: 'Practice typing code syntax'
passage_drill: 'Passage Drill'
passage_drill_desc: 'Type passages from books'
skill_tree: 'Skill Tree'
skill_tree_desc: 'View progression branches and launch drills'
keyboard: 'Keyboard'
keyboard_desc: 'Explore keyboard layout and key statistics'
statistics: 'Statistics'
statistics_desc: 'View your typing statistics'
settings: 'Settings'
settings_desc: 'Configure keydr'
day_streak: ' | %{days} day streak'
key_progress: ' Key Progress %{unlocked}/%{total} (%{mastered} mastered) | Target %{target} WPM%{streak}'
hint_start: '[1-3] Start'
hint_skill_tree: '[t] Skill Tree'
hint_keyboard: '[b] Keyboard'
hint_stats: '[s] Stats'
hint_settings: '[c] Settings'
hint_quit: '[q] Quit'
# Drill screen
drill:
title: ' Drill '
mode_adaptive: 'Adaptive'
mode_code: 'Code (Unranked)'
mode_passage: 'Passage (Unranked)'
focus_char: 'Focus: ''%{ch}'''
focus_bigram: 'Focus: "%{bigram}"'
focus_both: 'Focus: ''%{ch}'' + "%{bigram}"'
header_wpm: 'WPM'
header_acc: 'Acc'
header_err: 'Err'
code_source: ' Code source '
passage_source: ' Passage source '
footer: '[ESC] End drill [Backspace] Delete'
keys_reenabled: 'Keys re-enabled in %{ms}ms'
hint_end: '[ESC] End drill'
hint_backspace: '[Backspace] Delete'
# Dashboard / drill result
dashboard:
title: ' Drill Complete '
results: 'Results'
unranked_note_prefix: ' (Unranked'
unranked_note_suffix: ' does not count toward skill tree)'
speed: ' Speed: '
accuracy_label: ' Accuracy: '
time_label: ' Time: '
errors_label: ' Errors: '
correct_detail: ' (%{correct}/%{total} correct)'
input_blocked: ' Input temporarily blocked '
input_blocked_ms: '(%{ms}ms remaining)'
hint_continue: '[c/Enter/Space] Continue'
hint_retry: '[r] Retry'
hint_menu: '[q] Menu'
hint_stats: '[s] Stats'
hint_delete: '[x] Delete'
# Stats sidebar (during drill)
sidebar:
title: ' Stats '
wpm: 'WPM: '
target: 'Target: '
target_wpm: '%{wpm} WPM'
accuracy: 'Accuracy: '
progress: 'Progress: '
correct: 'Correct: '
errors: 'Errors: '
time: 'Time: '
last_drill: ' Last Drill '
vs_avg: ' vs avg: '
# Statistics dashboard
stats:
title: ' Statistics '
empty: 'No drills completed yet. Start typing!'
tab_dashboard: '[1] Dashboard'
tab_history: '[2] History'
tab_activity: '[3] Activity'
tab_accuracy: '[4] Accuracy'
tab_timing: '[5] Timing'
tab_ngrams: '[6] N-grams'
hint_back: '[ESC] Back'
hint_next_tab: '[Tab] Next tab'
hint_switch_tab: '[1-6] Switch tab'
hint_navigate: '[j/k] Navigate'
hint_page: '[PgUp/PgDn] Page'
hint_delete: '[x] Delete'
summary_title: ' Summary '
drills: ' Drills: '
avg_wpm: ' Avg WPM: '
best_wpm: ' Best WPM: '
accuracy_label: ' Accuracy: '
total_time: ' Total time: '
wpm_chart_title: ' WPM per Drill (Last 20, Target: %{target}) '
accuracy_chart_title: ' Accuracy %% (Last 50 Drills) '
chart_drill: 'Drill #'
chart_accuracy_pct: 'Accuracy %%'
sessions_title: ' Recent Sessions '
session_header: ' # WPM Raw Acc%% Time Date/Time Mode Ranked Partial'
session_separator: ' ─────────────────────────────────────────────────────────────────────'
delete_confirm: 'Delete session #%{idx}? (y/n)'
confirm_title: ' Confirm '
yes: 'yes'
no: 'no'
keyboard_accuracy_title: ' Keyboard Accuracy %% '
keyboard_timing_title: ' Keyboard Timing (ms) '
slowest_keys_title: ' Slowest Keys (ms) '
fastest_keys_title: ' Fastest Keys (ms) '
worst_accuracy_title: ' Worst Accuracy (%%) '
best_accuracy_title: ' Best Accuracy (%%) '
not_enough_data: ' Not enough data'
streaks_title: ' Streaks '
current_streak: ' Current: '
best_streak: ' Best: '
active_days: ' Active Days: '
top_days_none: ' Top Days: none'
top_days: ' Top Days: %{days}'
wpm_label: ' WPM: %{avg}/%{target} (%{pct}%%)'
acc_label: ' Acc: %{pct}%%'
keys_label: ' Keys: %{unlocked}/%{total} (%{mastered} mastered)'
ngram_empty: 'Complete some adaptive drills to see n-gram data'
ngram_header_speed_narrow: ' Bgrm Speed Expct Anom%'
ngram_header_error_narrow: ' Bgrm Err Smp Rate Exp Anom%'
ngram_header_speed: ' Bigram Speed Expect Samples Anom%'
ngram_header_error: ' Bigram Errors Samples Rate Expect Anom%'
focus_title: ' Active Focus '
focus_char_label: ' Focus: '
focus_bigram_value: 'Bigram %{label}'
focus_plus: ' + '
anomaly_error: 'error'
anomaly_speed: 'speed'
focus_detail_both: ' Char ''%{ch}'': weakest key | Bigram %{label}: %{type} anomaly %{pct}%%'
focus_detail_char_only: ' Char ''%{ch}'': weakest key, no confirmed bigram anomalies'
focus_detail_bigram_only: ' (%{type} anomaly: %{pct}%%)'
focus_empty: ' Complete some adaptive drills to see focus data'
error_anomalies_title: ' Error Anomalies (%{count}) '
no_error_anomalies: ' No error anomalies detected'
speed_anomalies_title: ' Speed Anomalies (%{count}) '
no_speed_anomalies: ' No speed anomalies detected'
scope_label_prefix: ' '
bi_label: ' | Bi: %{count}'
tri_label: ' | Tri: %{count}'
hes_label: ' | Hes: >%{ms}ms'
gain_label: ' | Gain: %{value}'
gain_interval: ' (every 50)'
focus_char_value: 'Char ''%{ch}'''
# Activity heatmap
heatmap:
title: ' Daily Activity (Sessions per Day) '
jan: 'Jan'
feb: 'Feb'
mar: 'Mar'
apr: 'Apr'
may: 'May'
jun: 'Jun'
jul: 'Jul'
aug: 'Aug'
sep: 'Sep'
oct: 'Oct'
nov: 'Nov'
dec: 'Dec'
# Chart
chart:
wpm_over_time: ' WPM Over Time '
drill_number: 'Drill #'
# Settings
settings:
title: ' Settings '
subtitle: 'Use arrows to navigate, Enter/Right to change, ESC to save & exit'
target_wpm: 'Target WPM'
theme: 'Theme'
word_count: 'Word Count'
ui_language: 'UI Language'
dictionary_language: 'Dictionary Language'
keyboard_layout: 'Keyboard Layout'
code_language: 'Code Language'
code_downloads: 'Code Downloads'
on: 'On'
off: 'Off'
code_download_dir: 'Code Download Dir'
snippets_per_repo: 'Snippets per Repo'
unlimited: 'Unlimited'
download_code_now: 'Download Code Now'
run_downloader: 'Run downloader'
passage_downloads: 'Passage Downloads'
passage_download_dir: 'Passage Download Dir'
paragraphs_per_book: 'Paragraphs per Book'
whole_book: 'Whole book'
download_passages_now: 'Download Passages Now'
export_path: 'Export Path'
export_data: 'Export Data'
export_now: 'Export now'
import_path: 'Import Path'
import_data: 'Import Data'
import_now: 'Import now'
hint_save_back: '[ESC] Save & back'
hint_change_value: '[Enter/arrows] Change value'
hint_edit_path: '[Enter on path] Edit'
hint_move: '[←→] Move'
hint_tab_complete: '[Tab] Complete (at end)'
hint_confirm: '[Enter] Confirm'
hint_cancel: '[Esc] Cancel'
success_title: ' Success '
error_title: ' Error '
press_any_key: 'Press any key'
file_exists_title: ' File Exists '
file_exists: 'A file already exists at this path.'
overwrite_rename: '[d] Overwrite [r] Rename [Esc] Cancel'
erase_warning: 'This will erase your current data.'
export_first: 'Export first if you want to keep it.'
proceed_yn: 'Proceed? (y/n)'
confirm_import_title: ' Confirm Import '
# Selection screens
select:
dictionary_language_title: ' Select Dictionary Language '
keyboard_layout_title: ' Select Keyboard Layout '
code_language_title: ' Select Code Language '
passage_source_title: ' Select Passage Source '
ui_language_title: ' Select UI Language '
more_above: '... %{count} more above ...'
more_below: '... %{count} more below ...'
current: ' (current)'
disabled: ' (disabled)'
enabled_default: ' (enabled, default: %{layout})'
enabled: ' (enabled)'
disabled_blocked: ' (disabled: blocked)'
built_in: ' (built-in)'
cached: ' (cached)'
disabled_download: ' (disabled: download required)'
download_required: ' (download required)'
hint_navigate: '[Up/Down/PgUp/PgDn] Navigate'
hint_confirm: '[Enter] Confirm'
hint_back: '[ESC] Back'
language_resets_layout: 'Selecting a language resets keyboard layout to that language''s default.'
layout_no_language_change: 'Layout changes do not change dictionary language.'
disabled_network_notice: 'Some languages are disabled: enable network downloads in intro/settings.'
disabled_sources_notice: 'Some sources are disabled: enable network downloads in intro/settings.'
passage_all: 'All (Built-in + all books)'
passage_builtin: 'Built-in passages only'
passage_book_prefix: 'Book: %{title}'
# Progress
progress:
overall_key_progress: 'Overall Key Progress'
unlocked_mastered: '%{unlocked}/%{total} unlocked (%{mastered} mastered)'
# Skill tree
skill_tree:
title: ' Skill Tree '
locked: 'Locked'
unlocked: 'unlocked'
mastered: 'mastered'
in_progress: 'in progress'
complete: 'complete'
locked_status: 'locked'
locked_notice: 'Complete %{count} primary letters to unlock branches'
branches_separator: 'Branches (available after %{count} primary letters)'
unlocked_letters: 'Unlocked %{unlocked}/%{total} letters'
level: 'Level %{current}/%{total}'
level_zero: 'Level 0/%{total}'
in_focus: ' in focus'
hint_navigate: '[↑↓/jk] Navigate'
hint_scroll: '[PgUp/PgDn or Ctrl+U/Ctrl+D] Scroll'
hint_back: '[q] Back'
hint_unlock: '[Enter] Unlock'
hint_start_drill: '[Enter] Start Drill'
unlock_msg_1: 'Once unlocked, the default adaptive drill will mix in keys in this branch that are unlocked.'
unlock_msg_2: 'If you want to focus only on this branch, launch a drill directly from this branch in the Skill Tree.'
confirm_unlock: 'Unlock %{branch}?'
confirm_yn: '[y] Unlock [n/ESC] Cancel'
lvl_prefix: 'Lvl'
branch_primary_letters: 'Primary Letters'
branch_capital_letters: 'Capital Letters'
branch_numbers: 'Numbers 0-9'
branch_prose_punctuation: 'Prose Punctuation'
branch_whitespace: 'Whitespace'
branch_code_symbols: 'Code Symbols'
level_frequency_order: 'Frequency Order'
level_common_sentence_capitals: 'Common Sentence Capitals'
level_name_capitals: 'Name Capitals'
level_remaining_capitals: 'Remaining Capitals'
level_common_digits: 'Common Digits'
level_all_digits: 'All Digits'
level_essential: 'Essential'
level_common: 'Common'
level_expressive: 'Expressive'
level_enter_return: 'Enter/Return'
level_tab_indent: 'Tab/Indent'
level_arithmetic_assignment: 'Arithmetic & Assignment'
level_grouping: 'Grouping'
level_logic_reference: 'Logic & Reference'
level_special: 'Special'
# Milestones
milestones:
unlock_title: ' Key Unlocked! '
mastery_title: ' Key Mastered! '
branches_title: ' New Skill Branches Available! '
branch_complete_title: ' Branch Complete! '
all_unlocked_title: ' Every Key Unlocked! '
all_mastered_title: ' Full Keyboard Mastery! '
unlocked: 'unlocked'
mastered: 'mastered'
use_finger: 'Use your %{finger}'
hold_right_shift: 'Hold Right Shift (right pinky)'
hold_left_shift: 'Hold Left Shift (left pinky)'
congratulations_all_letters: 'Congratulations! You''ve mastered all %{count} primary letters'
new_branches_available: 'New skill branches are now available:'
visit_skill_tree: 'Visit the Skill Tree to unlock a new branch'
and_start_training: 'and start training!'
open_skill_tree: 'Press [t] to open the Skill Tree now'
branch_complete_msg: 'You''ve completed the %{branch} branch!'
all_levels_mastered: 'All %{count} levels mastered.'
all_keys_confident: 'Every key in this branch is at full confidence.'
all_unlocked_msg: 'You''ve unlocked every key on the keyboard!'
all_unlocked_desc: 'Every character, symbol, and modifier is now available in your drills.'
keep_practicing_mastery: 'Keep practicing to build mastery — once every key reaches full'
confidence_complete: 'confidence, you''ll have achieved complete keyboard mastery!'
all_mastered_msg: 'Congratulations — you''ve reached full keyboard mastery!'
all_mastered_desc: 'Every key on the keyboard is at maximum confidence.'
mastery_takes_practice: 'Mastery is not a destination — it takes ongoing practice.'
keep_drilling: 'Keep drilling to maintain your edge.'
hint_skill_tree_continue: '[t] Open Skill Tree [Any other key] Continue'
hint_any_key: 'Press any key to continue'
input_blocked: 'Input temporarily blocked (%{ms}ms remaining)'
unlock_msg_1: 'Nice work! Keep building your typing skills.'
unlock_msg_2: 'Another key added to your arsenal!'
unlock_msg_3: 'Your keyboard is growing! Keep it up.'
unlock_msg_4: 'One step closer to full keyboard mastery!'
mastery_msg_1: 'This key is now at full confidence!'
mastery_msg_2: 'You''ve got this key down pat!'
mastery_msg_3: 'Muscle memory locked in!'
mastery_msg_4: 'One more key conquered!'
# Keyboard explorer
keyboard:
title: ' Keyboard '
subtitle: 'Press any key or click a key'
hint_navigate: '[←→↑↓/hjkl/Tab] Navigate'
hint_back: '[q/ESC] Back'
key_label: 'Key: '
finger_label: 'Finger: '
hand_left: 'Left'
hand_right: 'Right'
finger_index: 'Index'
finger_middle: 'Middle'
finger_ring: 'Ring'
finger_pinky: 'Pinky'
finger_thumb: 'Thumb'
overall_accuracy: ' Overall accuracy: %{correct}/%{total} (%{pct}%%)'
ranked_accuracy: ' Ranked accuracy: %{correct}/%{total} (%{pct}%%)'
confidence: 'Confidence: '
no_data: 'No data yet'
no_data_short: 'No data'
key_details: ' Key Details '
key_details_char: ' Key Details: ''%{ch}'' '
key_details_name: ' Key Details: %{name} '
press_key_hint: 'Press a key to see its details'
shift_label: 'Shift: '
shift_no: 'No'
overall_avg_time: 'Overall Avg Time: '
overall_best_time: 'Overall Best Time: '
overall_samples: 'Overall Samples: '
overall_accuracy_label: 'Overall Accuracy: '
branch_label: 'Branch: '
level_label: 'Level: '
built_in_key: 'Built-in Key'
unlocked_label: 'Unlocked: '
yes: 'Yes'
no: 'No'
in_focus_label: 'In Focus?: '
mastery_label: 'Mastery: '
mastery_locked: 'Locked'
ranked_avg_time: 'Ranked Avg Time: '
ranked_best_time: 'Ranked Best Time: '
ranked_samples: 'Ranked Samples: '
ranked_accuracy_label: 'Ranked Accuracy: '
# Intro dialogs
intro:
passage_title: ' Passage Downloads Setup '
code_title: ' Code Downloads Setup '
enable_downloads: 'Enable network downloads'
download_dir: 'Download directory'
paragraphs_per_book: 'Paragraphs per book (0 = whole)'
whole_book: 'whole book'
snippets_per_repo: 'Snippets per repo (0 = unlimited)'
unlimited: 'unlimited'
start_passage_drill: 'Start passage drill'
start_code_drill: 'Start code drill'
confirm: 'Confirm'
hint_navigate: '[Up/Down] Navigate'
hint_adjust: '[Left/Right] Adjust'
hint_edit: '[Type/Backspace] Edit'
hint_confirm: '[Enter] Confirm'
hint_cancel: '[ESC] Cancel'
preparing_download: 'Preparing download...'
download_passage_title: ' Downloading Passage Source '
download_code_title: ' Downloading Code Source '
book_label: ' Book: %{name}'
repo_label: ' Repo: %{name}'
progress_bytes: '[%{name}] %{downloaded}/%{total} bytes'
downloaded_bytes: 'Downloaded: %{bytes} bytes'
downloading_book_progress: 'Downloading current book: [%{bar}] %{downloaded}/%{total} bytes'
downloading_book_bytes: 'Downloading current book: %{bytes} bytes'
downloading_code_progress: 'Downloading: [%{bar}] %{downloaded}/%{total} bytes'
downloading_code_bytes: 'Downloading: %{bytes} bytes'
current_book: 'Current: %{name} (book %{done}/%{total})'
current_repo: 'Current: %{name} (repo %{done}/%{total})'
passage_instructions_1: 'keydr can download passages from Project Gutenberg for typing practice.'
passage_instructions_2: 'Books are downloaded once and cached locally.'
passage_instructions_3: 'Configure download settings below, then start a passage drill.'
code_instructions_1: 'keydr can download open-source code from GitHub for typing practice.'
code_instructions_2: 'Code is downloaded once and cached locally.'
code_instructions_3: 'Configure download settings below, then start a code drill.'
# Status messages (from app.rs)
status:
recovery_files: 'Recovery files found from interrupted import. Data may be inconsistent — consider re-importing.'
dir_not_exist: 'Directory does not exist: %{path}'
no_data_store: 'No data store available'
serialization_error: 'Serialization error: %{error}'
exported_to: 'Exported to %{path}'
export_failed: 'Export failed: %{error}'
could_not_read: 'Could not read file: %{error}'
invalid_export: 'Invalid export file: %{error}'
unsupported_version: 'Unsupported export version: %{got} (expected %{expected})'
import_failed: 'Import failed: %{error}'
imported_theme_fallback: 'Imported successfully (theme ''%{theme}'' not found, using default)'
imported_success: 'Imported successfully'
adaptive_unavailable: 'Adaptive ranked mode unavailable: %{error}'
switched_to: 'Switched to %{name}'
layout_changed: 'Layout changed to %{name}'
# Errors (for UI boundary translation)
errors:
unknown_language: 'Unknown language: %{key}'
unknown_layout: 'Unknown keyboard layout: %{key}'
unsupported_pair: 'Unsupported language/layout pair: %{language} + %{layout}'
language_blocked: 'Language is blocked by support level: %{key}'
# Common
common:
wpm: 'WPM'
cpm: 'CPM'
back: 'Back'