Open the web app here.
Download the RuneDroid mobile app from Google Play or build the APK yourself from this repository.
Use real runic inscriptions, both historical and from popular culture, to practice transliteration.
Ideally, I would like to become a collaborative effort where more enthusiasts would contribute and review each others' content.
Consider this screenshot of a popular cartoon Adventure Time, where Finn is pouring a liquid from a mug with a mysterious Anglo-Saxon inscription.
Under each runic symbol, there is a field to transliterate it to a latin character. For convenience, you can navigate with arrows between symbols as well as automatically jump to the next one.
At the bottom, there is a mini virtual keyboard with regional characters. In the bottom right, you can also open a cheat sheet.
There are two types of alphabets in the app:
- base alphabets
- inheriting alphabets
Base alphabets are:
- older futhark
- younger futhark long-branch
- younger futhark short-twig
- anglo-saxon
- medieval
Inheriting alphabets are local variations on the base alphabets. For example, a single rune has been flipped horizontally on a particular runestone.
All alphabets are stored in src/RuneRows.json
as a dictionary mapping ids to alphabets:
{
"$ID_1": {...},
"$ID_2": {...}
}
A base alphabet is defined as:
{
"name": "...",
"symbols": [
{
"rune": "X",
"latin: "X"
},
{
"rune": "X",
"latin: ["X", "X", ...]
},
...
]
}
where "X" stands for a single UTF-8 character.
An inheriting alphabet is defined as:
{
"name": "...",
"inherit_from": "$ID",
"override_symbols": [
{
"rune": "X",
"latin: "X"
},
{
"rune": "X",
"latin: ["X", "X", ...]
},
...
]
}
Exercises live in src/Exercises.json
. Follow the existing examples. Notes about the json schema:
id
is the unique identifier of the exercise,img
must be a valid image name existing inpublic/images
,img_credit
should be a link or a description where you got the image from. The app automatically distinguished between links and natural language descriptions, so you don't need to worry about how it will be displayed,title
is the displayed name of the exercise,rowType
is a valid ID of a row type fromsrc/RuneRows.json
. Note that in most cases, you'll want to create a new alphabet, inheriting from one of the base alphabets,description
is a short description of the historical or popular culture artifact concerned in the exercise. This is displayed before solving the exercise, so no spoilers please!runes
is either a string or a list of one-char strings. Note that:- each rune symbol must be present in the runic alphabet of choice (see
rowType
). - if you want to use separators (such as ":"), make sure they are recognized as separators by the
IsSeparator
function insrc/Utils.js
.
- each rune symbol must be present in the runic alphabet of choice (see
explanationAfter
explains the meaning of the transliteration after solving the exercise,sources
is a list of sources. You can mix valid links with non-link descriptions (such as book title).
After adding an exercise, start the server locally and verify that you can solve it in the app.
Contributions are very much welcome!
Here's how you can help grow the app:
- Directly contribute code.
- Improve test coverage.
- Provide mocks or sketches for better UI.
- Review existing content.
- Provide better sources.
- Submit new content (feel free to submit in any format, I'll be happy to convert to jsons).
- File an issue with your suggestions.
- ReactJS
- Node.js
- Clone the repository:
git clone https://github.com/tomaszgarbus/rune-ovningsbok
cd
intorune-ovningsbok
- Install Node dependencies:
npm install
- To run the tests:
npm test -- --coverage --watchAll
- You're good to go! Run
npm start
to run the app locally.
Deployment to GH pages was set up by following this guide. It suffices to run npm run deploy
from the main directory of the repo.
The entry point of the app is the "List of exercises" view. It shows all available exercises (without lazy loading) and displays all the images. To reduce the required network throughput, we display downsized thumbnails instead (if available).
Thumbnails are created automatically by img-resize workflow.
Thus, a good practice after adding a new exercise, is to wait for the img-resize
workflow to complete, download the generated artefact (a zip file with images) and extract it to public/images/thumbnails
.