Language Learner Tools WP Registry grade A. No security issues foundWP RegistryNo security issues foundOpen the reportA
A plugin for storing and displaying text, audio and image content for language learning
Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/stronganchor/language-learner-tools/releases/download/v6.7.34/language-learner-tools-6.7.34.zipA WordPress toolkit for building vocabulary-driven language learning sites. It provides custom post types and taxonomies, flashcard quizzes (with image + audio), auto-generated quiz pages, embeddable quiz pages, vocabulary grids, audio players, prompt cards, content lessons, teacher classes, bulk uploaders, DeepL-assisted translations, a template override system, and helper roles.
Developer navigation
- Codebase map: source owners, focused tests, and documentation by subsystem.
- Task router: choose a generated context pack from the reported behavior.
- Architecture: runtime load order, data model, routes, and invariants.
- Testing playbook and test setup: choose checks and prepare the local runtime.
- Release guide: packaged stable assets and branch/version gates.
The plugin requires WordPress 6.1+ and PHP 8.0+; the PHPUnit development suite
requires PHP 8.3+. Check language-learner-tools.php and tests/composer.lock
when changing those requirements.
Key Features
-
Post types & taxonomies
words,word_images,word_audio,ll_dictionary_entry,ll_vocab_lesson,ll_content_lesson,ll_prompt_card, andll_teacher_classpost types.- Taxonomies:
word-category,wordset,language,part-of-speech,recording_type.
-
Lessons & prompt cards
- Vocab lessons organize wordset/category study pages with lesson grids, prerequisites, category settings, and optional prompt-card rows.
- Content lessons support audio/video plus transcript cues and can appear in the same mixed wordset lesson grid as vocab lessons.
- Prompt cards provide prompt-first quiz items with text/audio/image prompts, answer-word references, recorder queue support, and progress tracking.
-
Flashcard quiz modes
- Practice Mode: Traditional quiz with adaptive difficulty based on performance.
- Learning Mode: Guided learning with word introduction, audio repetition, and progress tracking. Words are introduced gradually, and the system ensures mastery before moving forward.
- Listening / Gender / Self-check Modes: Additional mode variants for audio-first review, gender-aware drilling, and image-grouped confidence checks.
-
Flashcard quiz shortcode
[flashcard_widget]renders an interactive quiz. Attributes:category(slug or CSV),mode(random|image|text),embed(true|false),quiz_mode(practice|learning|listening|gender|self-check),wordset(filter by wordset),wordset_fallback(true|false).
-
Auto quiz pages & embed pages
- Auto-generated quiz pages under
/quiz/<category>. - Embeddable pages under
/embed/<category>render a minimal page that includes[flashcard_widget embed="true"]. - Both support wordset filtering and mode selection via URL parameters.
/embed/<category>supports?wordset=<slug>and?mode=<practice|learning|listening|gender|self-check>.
- Auto-generated quiz pages under
-
Audio recording & processing
- Audio Recorder Role: Dedicated user role for contributors to record audio.
- Recording Interface:
[audio_recording_interface]shortcode provides a browser-based recording interface. - Audio Processor: Admin tool to batch-process uploaded audio files and attach them to words.
- Audio-Image Matcher: Admin tool to quickly match audio and images where needed.
- Recording Types: Categorize audio as introduction, isolation, question, or sentence for contextual playback.
-
Other shortcodes
[ll_corpus_text_grid]/[ll_text_document_grid]- front-end content-lesson grid for corpus/text-document lessons.[word_grid]– grid of words with audio/text toggles, supports wordset filtering.[word_audio]– simple audio + (optional) text/translation for a single word.[ll_ranked_word_list]- bounded, paginated rank/word/translation/audio table for an exact word category and wordset.[ll_content_lesson_index]- bounded, paginated content-lesson index scoped to one wordset and optional retained legacy category IDs.[ll_interlinear]- compact interlinear table using the shared LL Tools interlinear renderer.[ll_mark tone="orange"]...[/ll_mark]- bold inline lesson-text mark withorange,blue, orgreentones. Legacy[color1],[color2], and[color3]tags remain compatible.[editor_hub]- editor-facing workflow for filling missing word metadata and recording details. Maintenance note: hidden from the primary front-end utility nav; review for a focused rebuild or removal before promoting as an active workflow.[wordset_page]/[ll_wordset_page]– front-end wordset hub with study, progress, and manager views.[ll_language_switcher]– front-end locale switcher for the plugin’s available translations.[ll_locale_block]- conditionally renders enclosed content for matching locale language keys.[image_copyright_grid posts_per_page="12"]– paginated grid ofword_images.- Quiz listings:
[quiz_pages_grid]and[quiz_pages_dropdown], both support wordset filtering and popup mode.
-
Admin UX
- Bulk audio and image uploaders that can create/update posts and try to match media to posts by name.
- Audio Processor: Batch-process uploaded audio files and attach them to words.
- Audio-Image Matcher: Match audio files to images with scoring and usage tracking.
- Offline App Export: Build a single-wordset offline quiz bundle with media, optional local STT games, and local-first progress sync back to the site.
- Wordset manager workflows via the plugin’s custom wordset pages.
- Teacher classes scoped to wordsets, with invite links, manual learner assignment, and sortable student progress views.
- Settings page (translations, browser-language auto-switch, DeepL API key, image size, font, option caps, etc.).
-
DeepL integration
- Optional: store a DeepL API key and enable category term translations in the UI.
-
Templating
- Child/parent theme template overrides via
ll-tools/...inside the active theme, with a safe loader.
- Child/parent theme template overrides via
-
Roles
wordset_manager– Can manage wordsets and basic content.ll_tools_editor– Can upload files, edit categories/wordsets, and access LL Tools pages.audio_recorder– Dedicated role for audio recording contributors with limited admin access.
-
Update checker
- Uses Yahnis Elsts' Plugin Update Checker.
Mainpulls packaged GitHub release assets for production updates.Devremains a GitHub branch-based testing channel.
Installation
- Upload or clone the plugin into
wp-content/plugins/language-learner-tools. - Activate it in Plugins.
- (If
/quizor/embedinitially 404) Go to Settings → Permalinks and click Save to refresh rewrites. - Open Settings → Language Learner Tools (or click the Settings link under the plugin on the Plugins screen) to review options.
Quick Start
-
Create terms in Word Category, Word Set, Language and Part of Speech.
-
Add Words: set the title, featured image (optional), attach audio as needed, and assign Word Category terms.
- Audio may be required before publish or quiz use when the assigned category configuration requires approved recordings.
-
Drop a flashcard quiz anywhere:
[flashcard_widget category="animals" quiz_mode="learning"]quiz_mode="practice"for traditional adaptive quizzing (default)quiz_mode="learning"for guided learning with word introduction- To embed a minimal page for a category, link to
/embed/animals,/embed/animals?mode=<practice|learning|listening|gender|self-check>, or/embed/animals?wordset=<slug>&mode=<practice|learning|listening|gender|self-check>.
-
Make a grid of words:
[word_grid category="animals" columns="4" limit="24" show_audio="true" show_text="translation" wordset="beginner"]For a large ordered reference collection, use the bounded ranked list instead:
[ll_ranked_word_list category="most-common-words" wordset="beginner" per_page="50"] -
Single-word audio on lesson pages:
[word_audio id="123" translate="yes"] -
Show which images need copyright info:
[image_copyright_grid posts_per_page="12"] -
List quiz categories:
[quiz_pages_grid wordset="beginner" popup="yes" mode="learning"] [quiz_pages_dropdown wordset="advanced"] -
Audio recording interface for contributors:
[audio_recording_interface] -
Legacy/review-candidate editor-facing missing-content workflow:
[editor_hub] -
Optional front-end locale switcher:
[ll_language_switcher] [ll_locale_block lang="tr"]Turkish-only content[/ll_locale_block]
Command-Line Automation
For Codex/operator workflows, LL Tools now exposes plugin-owned WP-CLI commands under wp ll-tools ... so common maintenance no longer has to drive wp-admin forms or AJAX.
Use WP-CLI as the execution plane for trusted server-side maintenance, especially when a task touches hundreds of rows and each row performs expensive validation, media work, taxonomy repair, cache rebuilding, or filesystem access. Keep using dry runs, resume files, and summary files so Codex can review and verify the work.
Use hyphenated subcommands such as wordset-report; underscore variants remain
available as compatibility aliases.
Examples:
wp --path=/path/to/site/public ll-tools wordset-create "Spanish Travel" --template=travel-template
wp --path=/path/to/site/public ll-tools wordset-missing-meta spanish --fields=part_of_speech,grammatical_gender --format=json
wp --path=/path/to/site/public ll-tools word-bulk-update spanish --where-missing=grammatical_gender --set=grammatical_gender=Feminine --dry-run
wp --path=/path/to/site/public ll-tools wordset-report spanish --summary-file=tmp/spanish-report.json
From this plugin checkout you can also use bash bin/ll-wp.sh ... as a convenience wrapper when wp is already installed in PATH.
See docs/CLI_AUTOMATION.md for the recommended workflow, supported update fields, dry-run/resume usage, and reporting details.
For a post-based lesson/prerequisite cutover, follow the guarded
legacy lesson migration runbook.
The bounded --retained-source lessons mode creates an empty, published
compatibility target for an explicitly named source post that must keep its
editorial URL/body; the target remains available to prerequisite/completion
mapping but is excluded from normal public lesson catalogs and redirects direct
requests to the retained source. The temporary [display_prereq_tree] shim may
show a compact source-linked card for a valid retained target so legacy index
navigation keeps that editorial resource discoverable.
REST Automation
If you want to keep a temp WordPress admin or manager user workflow instead of
server shell access, LL Tools also exposes REST automation routes under
/wp-json/ll-tools/v1/....
REST automation is the control plane: use it for status checks, reports, dry runs, job start/status/result calls, cache purges, and bounded mutation chunks. For large expensive operations, prefer an existing job-style route, a new server-side job wrapper, or WP-CLI rather than one long synchronous HTTP request.
These routes support:
- logged-in browser sessions with REST nonce
- WordPress Application Passwords
- LL Tools password-based Basic auth using the site's normal WordPress username and password
Examples:
curl -u codex-temp:YOUR_PASSWORD https://example.com/wp-json/ll-tools/v1/automation/status
curl -u codex-temp:YOUR_PASSWORD https://example.com/wp-json/ll-tools/v1/wordsets/spanish/report
curl -u codex-temp:YOUR_PASSWORD "https://example.com/wp-json/ll-tools/v1/wordsets/spanish/missing-meta?fields=part_of_speech,grammatical_gender"
See docs/REST_AUTOMATION.md for the full route list, request bodies, auth notes, bulk-update/resume examples, and the REST control plane versus server-side execution model.
For this Local/WSL checkout, use bash bin/ll-rest-local.sh ... when Linux
curl cannot reach the Windows-hosted Local listener directly.
Shortcodes (details)
[flashcard_widget]
- Attributes
category: targetword-categoryterm slug (CSV accepted).mode:random(default),image, ortext.embed:true|false(usetruefor compact UI on/embed/<slug>pages).quiz_mode:practice(default),learning,listening,gender, orself-check.wordset: filter words by wordset slug/name/id.wordset_fallback:true|false; when enabled, empty wordset filters fall back to the active/default wordset.
[word_grid]
- Common attributes:
limit,columns,category,language,sort_by,transliterate,show_audio,show_text(values liketarget|translation|both|none),wordset.
[ll_ranked_word_list]
- Renders one bounded page of published
wordsin an exactword-categoryand exact visiblewordset, ordered by the numeric_ll_tools_word_rankmeta value and then by word ID for stable ties. Both scopes are required so a public category cannot expose words from a private wordset. - Attributes:
category: requiredword-categoryslug or term ID.wordset: requiredwordsetslug or term ID.per_page: defaults to50and is hard-capped at100.list_id: optional stable scope for the list's page query argument. Use distinct values when the same category appears in multiple independently paged lists on one page.
- Each page bulk-primes its word metadata/terms and collects audio for only the displayed word IDs. It does not hydrate the complete category as
[word_grid]currently can. Navigation is capped at 100 pages; when a scope exceeds that bound, the shortcode shows an explicit truncation notice instead of emitting unreachable links. - Trusted migration code can call
ll_tools_import_ranked_word_rows()with bounded associative rows containingrankplusword_id/idortitle/word. The helper is idempotent, uses only the allowlisted rank meta key, caps batches at 200 rows, and performs at most a two-result exact-title lookup; callers remain responsible for capability/nonce checks and CSV parsing.
[word_audio]
- Attributes:
id: the Word post ID.translate:yes|no(show the translation next to the audio button).recording_type: specificrecording_typeslug to play, such asintroduction.word_audio_id: exactword_audiopost ID to play.
[ll_interlinear]
- Renders a compact public interlinear table with the shared LL Tools interlinear markup and CSS.
- Attributes:
text: optional source line rendered as aSentencerow.show_text:1|0; defaults to1.translation/free_translation/free: optional free translation rendered as a final row.class: optional extra wrapper class.
- Content format: one row per line, using
|or tabs. The first cell is the row label; supported labels areSENTENCE/TEXT,FORM/WORD,MORPH,LEMMA,GLOSS,POS, andFREE/FREE_TRANSLATION.SENTENCE/TEXTandFREE/FREE_TRANSLATIONsplit only on the first separator and render as a single content cell; analysis rows render as aligned table columns.
[ll_interlinear]
SENTENCE | Lac qicik
MORPH | lac | ∅ | qicik
GLOSS | son | M.EZ | small
FREE | little boy
[/ll_interlinear]
[ll_mark] / [color1] / [color2] / [color3]
[ll_mark tone="orange"]...[/ll_mark]adds a bold, inline lesson-text mark without inline styles.- Attributes:
tone:orange(default),blue, orgreen.
- Existing content can keep using
[color1](orange),[color2](blue), and[color3](green). These compatibility tags ignore attributes and retain the historical colors; canonical[ll_mark]adds darker accessible colors and distinct underline cues. - Enclosed inline markup and shortcodes are supported; block wrappers are removed while their text remains so the emitted
<span>stays valid.
[ll_content_lesson_index]
- Renders published non-corpus content lessons for exactly one visible wordset, grouped by lesson level.
- Attributes:
wordset: wordset ID, slug, or name. When omitted, the resumable legacy lesson migration's saved compatibility wordset is used.categories: optional comma-separated legacy WordPress category IDs retained on migrated lessons.per_page: defaults to50and is hard-capped at100.list_id: optional stable key for an independent pagination query argument when a page contains more than one index.show_excerpt:1|0; defaults to1.
- Numeric pagination is capped at 100 pages, and each request fetches only the selected page plus one continuation row.
- Temporary migration shims are available for
[display_prereq_tree],[custom_header],[custom_footer],[regex_linker], and[signup_link]only when another plugin has not already registered the tag. The shims use migrated content-lesson mappings and bounded prerequisite/dependent queries. The old debug and global CSS-dequeue behavior are intentionally not included.
[image_copyright_grid]
- Attributes:
posts_per_page: default12.
[editor_hub]
- Editor-facing review flow for missing word fields, dictionary entry links, images, and recording metadata.
- Maintenance note: this surface is no longer linked from the primary front-end utility nav and should be reviewed for either a focused rebuild or removal if it is not serving active users.
[wordset_page] / [ll_wordset_page]
- Front-end wordset hub that renders the current wordset context, including study/progress/settings views.
- Attributes:
wordset,slug, orid: explicit wordset reference.show_title:1|0; defaults to1.preview_limit: number of preview items per category card; defaults to2.class: extra wrapper classes.redirect_to_canonical:1|0; defaults to0. Use1on a retired page with a different slug to issue a query-preserving 301 to the dedicated/<wordset>/route.
- Word Set Tools → Study includes a default-on setting that can remove content lessons from the wordset home while keeping those lessons available through direct links and
[ll_content_lesson_index]. - Word Set Tools → Categories can add one optional, compact reference link to an individual category card. Use a site-relative path for a same-site long-form resource so exports and local/live copies stay portable.
[wordset_buttons] / [ll_wordset_buttons]
- Front-end list of word set launch buttons.
- Attributes:
hide_empty(1|0to hide word sets without learner-ready categories),class.
[ll_language_switcher]
- Locale choices submit as nonce-protected POST forms; legacy signed GET locale URLs remain accepted for inbound compatibility and redirect back to the clean current URL.
- Attributes:
show_flags:1|0to show or hide locale flags.style:native,english, orcode.display:list,dropdown,button, ormodal.primary_locales: comma/space/pipe-separated locale list to keep as top-level choices, such astr_TR,en_US,de_DE.primary_count: number of locales to keep as top-level choices before placing the rest under the secondary bucket.secondary_label: accessible label for the secondary reveal button; defaults toOther languages.class: extra CSS class for wrapper styling.
[ll_locale_block]
- Renders enclosed content only when the current plugin locale language key matches.
- Attributes:
lang/language: language keys or locale codes, separated by commas, spaces, or pipes.
[ll_dictionary] / [dictionary_search] / [dictionary_browser]
- Front-end dictionary browser/search surface.
- Attributes:
wordset,show_title,per_page,sense_limit,linked_word_limit,title,gloss_lang.
[ll_corpus_text_grid] / [ll_text_document_grid]
- Front-end grid of corpus/text-document content lessons.
- Attributes:
wordset,limit,columns,show_excerpt,show_sources,class.
[quiz_pages_grid] / [quiz_pages_dropdown]
- Attributes (grid):
show_counts,exclude,parent,order,orderby,wordset,popup(yesto open flashcard overlay inline),mode(practice,learning, orself-check). - Attributes (dropdown):
wordset,placeholder,button(yesto show a Go button).
[audio_upload_form] / [image_upload_form]
- Manager/admin upload forms for bulk audio and image uploads.
- Attributes:
wordset_id,lock_wordset,return_url.
[audio_recording_interface]
- Provides a browser-based interface for recording audio.
- Best used with the Audio Recorder role for contributors.
[audio_credit_grid]
- Public credit grid for recordings with attribution metadata.
- Attributes:
posts_per_page.
[ll_site_tools]
- Front-end tools hub for users with LL Tools permissions.
Learning Mode
Learning Mode is an adaptive learning system that guides users through vocabulary acquisition:
- Word Introduction: New words are introduced in small batches (1-2 at a time) with audio repetition.
- Progressive Difficulty: The number of answer choices adapts based on performance (2-5 options).
- Mastery Tracking: Each word must be answered correctly 3 times before it's considered learned.
- Smart Sequencing: Words are reintroduced if answered incorrectly, with spacing to avoid frustration.
- Progress Visualization: A dual-progress bar shows both introduction progress and mastery progress.
- Audio Context: Uses different recording types (introduction vs. question) for varied learning contexts.
To use Learning Mode:
[flashcard_widget category="animals" quiz_mode="learning"]
Or link to: /quiz/animals?mode=learning
Audio Recording & Processing Workflow
For Contributors (Audio Recorder Role)
- Recording Interface: Use the
[audio_recording_interface]shortcode on a page. - Browser Recording: Record directly in the browser with playback preview.
- Upload: Submit recordings for processing.
For Administrators
-
Audio Processor (
Tools → Audio Processor):- Batch-process uploaded audio files.
- Automatically match audio to words by filename.
- Assign recording types (introduction, isolation, question, sentence).
- Create
word_audioposts and attach to words.
-
Audio-Image Matcher (
Tools → Audio-Image Matcher):- Match audio files to images.
- Uses fuzzy matching and scoring.
- Tracks image usage to promote variety.
-
Recording Types Admin (
Tools → Recording Types):- Manage the recording type taxonomy.
- Categorize audio for contextual use.
Offline App Export & Sync
-
Offline bundle export (
Tools → Offline App Export)- Exports exactly one word set per bundle.
- Stages the standalone offline shell, quiz/game runtime assets, and bundled media needed for supported modes.
- Can include local STT-backed game content when the selected word set has an offline model bundle configured.
-
Local-first progress
- Learners can keep using the exported app while fully offline.
- Progress is stored locally in the app until the learner reconnects.
- The app can later sign in against the source site and sync saved progress back through the plugin’s offline sync endpoint.
-
What to verify after export
- The selected word set has enough usable media for the intended quiz/game modes.
- The generated zip includes the offline shell plus plugin media assets, not the full repository.
- If sync is intended, the source site remains reachable and the learner has an account with access to the same word set.
Recording Types
Audio files can be categorized by recording type:
- Introduction: Full introduction audio (e.g., "Merhaba. That means hello in Turkish.")
- Isolation: Word spoken in isolation
- Question: Word used in a question
- Sentence: Word used in a sentence
The flashcard widget intelligently selects the appropriate recording type based on context (learning mode uses introduction audio, practice mode uses question audio).
Settings
-
Translations
- Enable category term translations (optional).
- If enabled, you can store a DeepL API key for supported translation helpers such as category-name translation.
- Optional browser-language auto-switch uses the visitor locale until they pick a different plugin language.
-
Flashcards
- Image size used in quizzes.
- Max options override for multiple-choice layout.
- Font selection for the quiz.
-
Admin
- Show/hide audio & image upload tools.
- Lightweight capability
view_ll_toolsgates certain admin pages.
Find the settings via the plugin's Settings link on the Plugins page or under Settings → Language Learner Tools.
Testing
The maintained local test entry points are documented in:
tests/AI_TESTING_PLAYBOOK.mdfor AI/operator workflow guidance.tests/README.mdfor PHPUnit, Playwright, Local environment detection, and troubleshooting.
Local Dev / Media Proxy Notes
- Local Live Link (
*.localsite.io) is auto-detected for media URL rebasing/proxy behavior. X-Forwarded-*and Local tunnel headers are now trusted only in narrow contexts by default (to reduce header spoofing risk).- If you run behind a custom trusted proxy/tunnel in development, you can opt in with:
ll_tools_media_proxy_trust_forwarded_headersll_tools_media_proxy_trust_tunnel_headers
Templating
You can override plugin templates by placing files under:
/wp-content/themes/<child-or-parent>/ll-tools/<relative-path>
For example, copy:
wp-content/plugins/language-learner-tools/templates/flashcard-widget-template.php
to:
wp-content/themes/your-child-theme/ll-tools/flashcard-widget-template.php
Roles
- Word Set Manager (
wordset_manager): basic content + word set management. - LL Tools Editor (
ll_tools_editor): can upload files, edit categories/word sets, and access LL Tools pages (viaview_ll_tools). - Audio Recorder (
audio_recorder): dedicated role for audio recording contributors with limited admin access.
The admin menu is trimmed for these roles to focus on LL Tools–related items.
Update Checker
The plugin includes the Plugin Update Checker library.
Mainstable updates come from a packaged GitHub release asset zip, not the raw source archive.Devremains branch-based for testing and can include development-only repository files.- Maintainers should follow the release steps in RELEASING.md.
Notes
- After activation, the plugin creates/maintains pages for each
word-categoryunder/quiz/.... - Embedded quiz pages are handled purely by rewrite + template, not by requiring the PHP directly in bootstrap (clean separation).
- Learning mode introduces words gradually and tracks mastery (3 correct answers per word).
- Audio files can have multiple recordings per word (introduction, isolation, question, sentence) for contextual use.
License
GPL-compatible. See source headers.
Releases
12 releases. Each count is every asset in that release; expand a row for the breakdown.