Ludum Linguarum is a set of tools and recipes to extract localized content (currently just text) from a set of supported games, which can then be turned into flash cards for use with the following spaced repetition software:
In other words, you can spice up your language learning regimen by drilling yourself with flash cards containing text from video games!
The list of 64 currently supported games can be found here. Currently only PC games are supported, although there's no technical reason other platforms couldn't be supported -- it's just simpler to work on PC versions of titles.
Ludum Linguarum can run on Windows, Linux, and OS X! (Some titles may only be supported under Windows.)
This walkthrough covers setting up Ludum Linguarum, the Anki desktop client, importing text from a game, exporting it to a format that Anki can recognize, and then importing it into Anki and using the flashcards to drill.
LudumLinguarum list-supported-games
to find the name of the game that you want to extract.LudumLinguarum import --game="<game name>" --game-dir="<root directory of game>"
to import the game text. (Some games
that only support a single language with their installed data may require you to specify the language with --language-tag=<language tag>
.)LudumLinguarum export-anki --game="<game name>" --recognition-language="<first language>" --production-language="<second language>" --export-path="<path to export file>" --production-word-limit=5
. The "recognition language" is the
two-letter language code for the language you are more familiar with,
and the "production language" is the language code for the one you're trying to learn. Examples are "en" for English,
"fr" for French, "de" for German, "ja" for Japanese, and so on. (Flash cards will be generated for translating in both directions.)
export-path
is the output text file, which will be imported into Anki in the next step, and 'production-word-limit' restricts the length of
text to 5 whitespace-separated words in the target language, which can be useful for limiting the flash cards to shorter phrases or vocabulary.I also recommend setting up an AnkiWeb account, as this will let you sync your progress between the desktop and mobile clients. This makes it easy to practice on the go!
This walkthrough covers setting up Ludum Linguarum, importing text from a game, exporting it to a format that will work with SuperMemo's online importer, and then importing it and using the flashcards to drill.
LudumLinguarum list-supported-games
to find the name of the game that you want to extract.LudumLinguarum import --game="<game name>" --game-dir="<root directory of game>"
to import the game text. (Some games
that only support a single language with their installed data may require you to specify the language with --language-tag=<language tag>
.)LudumLinguarum export-supermemo --game="<game name>" --recognition-language="<first language>" --production-language="<second language>" --export-path="<path to export file>" --production-word-limit=5
. The "recognition language" is the
two-letter language code for the language you are more familiar with,
and the "production language" is the language code for the one you're trying to learn. Examples are "en" for English,
"fr" for French, "de" for German, "ja" for Japanese, and so on. (Flash cards will be generated for translating in both directions.)
export-path
specifies the output text file (or files -- your export will be split up into files of 99 cards each, which matches SuperMemo's limit
of how many cards you can import at once), which will be imported into SuperMemo in the next step, and 'production-word-limit' restricts the length of
text to 5 whitespace-separated words in the target language. This can be useful for limiting the flash cards to shorter phrases or vocabulary.This walkthrough importing text from a game, exporting it to a format that Mnemosyne can recognize, and then importing it into Mnemosyne and using the flashcards to drill.
LudumLinguarum list-supported-games
to find the name of the game that you want to extract.LudumLinguarum import --game="<game name>" --game-dir="<root directory of game>"
to import the game text. (Some games
that only support a single language with their installed data may require you to specify the language with --language-tag=<language tag>
.)LudumLinguarum export-mnemosyne --game="<game name>" --recognition-language="<first language>" --production-language="<second language>" --export-path="<path to export file>" --production-word-limit=5
. The "recognition language" is the
two-letter language code for the language you are more familiar with,
and the "production language" is the language code for the one you're trying to learn. Examples are "en" for English,
"fr" for French, "de" for German, "ja" for Japanese, and so on. (Flash cards will be generated for translating in both directions.)
export-path
is the output text file, which will be imported into Anki in the next step, and 'production-word-limit' restricts the length of
text to 5 whitespace-separated words in the target language, which can be useful for limiting the flash cards to shorter phrases or vocabulary.If you want to focus on particular types of cards (i.e. short vocabulary words, instead of translating dialogue), don't hesitate to use Anki's "bury" or "delete" functions -- "bury" will send the card to the bottom of the deck, while "delete" will completely remove it. Also, depending on whether a game's extraction recipe breaks it down this way, you may be able to filter on extraction by "lesson" name -- see the command-line help for more details about this.
Depending on the game, sometimes the extraction isn't 100% clean. Please let me know if you run into problems -- and in the meantime, you can always delete incorrect cards from your decks so you can continue working with them in the meantime.
Yes! Lots of free and commercial software and services are based around these ideas, including Duolingo, Course Hero, and Memrise. I would strongly encourage you to try it out if you are skeptical -- you'll find it starts to improve your recall almost immediately, and daily practice will build up your vocabulary quite quickly.
You should use this as a fun supplement to other language learning resources, like classes, study groups, etc. Using flash cards generated by this isn't going to teach you the very basics of a language, pronunciation, grammar, etc. -- it is a very effective way of expanding your vocabulary, and seeing a huge corpus of text in a foreign language. If you've already played the game whose text you've exported (in a language you understand), it can be quite helpful in rapidly learning the deck. It's not a requirement, though -- you can just as easily use this to enable you to play a game 'cold' in another language!
Check the list of currently supported games here. The release notes file also lists supported games, along with the version number in which they were implemented.
No. It's copyrighted content. Not gonna happen.
Thanks for asking! The answer is, "maybe," depending on how difficult it is to extract the content from the game.
I've drawn up a list of games that have been investigated and are either definitively unsupportable (i.e. their localized text is all stored as bitmaps, etc.), or are unlikely to be supported due to the difficulty in reverse-engineering their file formats.
Some characteristics that might make it easier to support a particular game:
I am definitely on the lookout for games that meet these criteria, as I can add support for them quickly. If you know of games that definitely meet these criteria, please contact me (see below) and let me know!
If a game doesn't match any of these characteristics, it doesn't mean that it's impossible to add support, but it may be very difficult or time-consuming to do. Code contributions and pull requests are always welcome, so if you are technically inclined and sufficiently motivated, you can do it yourself!
Look at the OneOffGamesPlugin project within the source for some small, self-contained examples. Essentially, the plugin registers a bunch of game names that it recognizes, and then gets called by the main application to extract the text, and generate the "cards" to be written to the SQLite database that contains all of the extracted content. SimpleGames.fs contains the simplest implementations of extraction -- some of them are just a few lines of code!
The project has a Twitter account, @LudumLinguarum. You can also contact me (Erik Novales) at @yankeefinn.
GitHub Actions |
---|
Package | Stable | Prerelease |
---|---|---|
LudumLinguarum |
Make sure the following requirements are installed on your system:
or
CONFIGURATION
will set the configuration of the dotnet commands. If not set, it will default to Release.
CONFIGURATION=Debug ./build.sh
will result in -c
additions to commands such as in dotnet build -c Debug
GITHUB_TOKEN
will be used to upload release notes and NuGet packages to GitHub.
DISABLE_COVERAGE
Will disable running code coverage metrics. AltCover can have severe performance degradation so it's worth disabling when looking to do a quicker feedback loop.
DISABLE_COVERAGE=1 ./build.sh
> build.cmd <optional buildtarget> // on windows
$ ./build.sh <optional buildtarget>// on unix
Clean
- Cleans artifact and temp directories.DotnetRestore
- Runs dotnet restore on the solution file.DotnetBuild
- Runs dotnet build on the solution file.DotnetTest
- Runs dotnet test on the solution file.GenerateCoverageReport
- Code coverage is run during DotnetTest
and this generates a report via ReportGenerator.WatchApp
- Runs dotnet watch on the application. Useful for rapid feedback loops.WatchTests
- Runs dotnet watch with the test projects. Useful for rapid feedback loops.GenerateAssemblyInfo
- Generates AssemblyInfo for libraries.CreatePackages
- Runs the packaging task from dotnet-packaging. This creates applications for win-x64
, osx-x64
and linux-x64
- Runtime Identifiers.
win-x64
application in a .zip file.osx-x64
application in a .tar.gz file.linux-x64
application in a .tar.gz file.GitRelease
- Creates a commit message with the Release Notes and a git tag via the version in the Release Notes
.GitHubRelease
- Publishes a GitHub Release with the Release Notes and any NuGet packages.FormatCode
- Runs Fantomas on the solution file.Release
- Task that runs all release type tasks such as GitRelease
and GitHubRelease
. Make sure to read Releasing to setup your environment correctly for releases.git add .
git commit -m "Scaffold"
git remote add origin https://github.com/user/MyCoolNewApp.git
git push -u origin master
GITHUB_TOKEN
to upload release notes and artifacts to githubThen update the CHANGELOG.md
with an "Unreleased" section containing release notes for this version, in KeepAChangelog format.
NOTE: Its highly recommend to add a link to the Pull Request next to the release note that it affects. The reason for this is when the RELEASE
target is run, it will add these new notes into the body of git commit. GitHub will notice the links and will update the Pull Request with what commit referenced it saying "added a commit that referenced this pull request". Since the build script automates the commit message, it will say "Bump Version to x.y.z". The benefit of this is when users goto a Pull Request, it will be clear when and which version those code changes released. Also when reading the CHANGELOG
, if someone is curious about how or why those changes were made, they can easily discover the work and discussions.
Here's an example of adding an "Unreleased" section to a CHANGELOG.md
with a 0.1.0
section already released.
## [Unreleased]
### Added
- Does cool stuff!
### Fixed
- Fixes that silly oversight
## [0.1.0] - 2017-03-17
First release
### Added
- This release already has lots of features
[Unreleased]: https://github.com/user/MyCoolNewApp.git/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/user/MyCoolNewApp.git/releases/tag/v0.1.0
Release
target, specifying the version number either in the RELEASE_VERSION
environment
variable, or else as a parameter after the target name. This will:
CHANGELOG.md
, moving changes from the Unreleased
section into a new 0.2.0
sectionBump version to 0.2.0
and adds the new changelog section to the commit's bodymacOS/Linux Parameter:
./build.sh Release 0.2.0
macOS/Linux Environment Variable:
RELEASE_VERSION=0.2.0 ./build.sh Release
Copyright (c) 2007‒2017, Stephan Tolksdorf. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
This software is provided by the copyright holders “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright holders be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
MIT License
Copyright (c) 2022 Greg Dennis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.