Skip to content

H5P's own strings follow the content's language - #56

Merged
alekswebnet merged 3 commits into
mainfrom
feat/strings-follow-content
Oct 20, 2026
Merged

alekswebnet merged 3 commits into
mainfrom
feat/strings-follow-content

Conversation

@alekswebnet

Copy link
Copy Markdown
Contributor

Closes #55. Replaces #54, a language select, closed unmerged: a select could only make the interface and the content differ.

H5P's own buttons and dialogs followed the element's lang, usually inherited from the page. The content's own text, its questions and its Check and Retry buttons, is in the language its author wrote it in. So a page in another language showed two at once: "Vollbild" and "Nutzungsrechte" around an English quiz.

Changes

  • The worker (frame-document.ts): one function, frameLanguage, decides the frame's language:

    • h5p.json's defaultLanguage, which the worker already wrote as the frame's <html lang>, as H5P does for the iframe it makes;
    • else the element's lang, for a package that names none or says und;
    • else English.

    H5P's strings, the runtime's l10n.js and the frame's policy for it now all follow that language. Before, only <html lang> did. Nothing changes in the element or the runtime.

  • The embed page: &lang= still reaches the element, and is the same fallback. Its comment and README row say so.

  • Docs: the README's lang row and feature bullet, the h5p-standalone guide's translations row, the setup skill and AGENTS.md now describe the content's language first, lang as the fallback.

  • Two-players example: the second player drops lang="de". Its package is English, so the attribute no longer changed anything. The page's text no longer says "in German".

Compatibility

lang is in the README's API table, which docs/compatibility.md covers, and what it does changes: for a package that names its language, lang no longer decides. A host that set lang to put German buttons around English content gets English buttons now. Strictly, by the doc, that is a major. The release decides whether it goes out as a 2.0 or as a 1.1 with the change listed first in the notes. The code is the same either way.

Testing

  • New browser test (l10n.test.ts): a German package on an English page shows "Vollbild" and "Namensnennung" and loads the translations. An English package in a German element shows "Fullscreen" and loads none. The German package from a host without Range, where the frame boots before the download ends, is German too. It fails against the old worker ("expected 'Fullscreen' to be 'Vollbild'") and passes in Chromium, Firefox and WebKit.
  • New fixtures: german.h5p and english.h5p are basic.h5p naming its language. basic.h5p names none, so the existing language tests are now the fallback case, and they pass unchanged.
  • Unit tests (frame-document.test.ts): the content's language in both directions, the element's for none or und, no translations for any English, and the translations' origin in the policy for the content's language, by exact path when untrusted.
  • The embed's test of &lang=de on the English demo quiz now expects the element to get de and the strings to be English.
  • Suites: typecheck passes in every package. Player: 344 unit and 191 browser tests in Chromium. Embed: 26 of 26.

Release

  • The player, a minor or a major as above: the change is in the worker, so it reaches a host with the new h5p-sw.js.
  • The embed needs nothing of its own. A site written again after the player release gets the new worker.

🤖 Generated with Claude Code

alekswebnet and others added 3 commits October 20, 2026 14:34
H5P's buttons and dialogs followed the element's `lang`, usually the
page's, while the content's own text — its questions, its Check and
Retry — is in the language its author wrote it in. A page whose language
differed showed both at once: "Vollbild" around an English quiz.

The worker now writes the frame in the content's language,
`h5p.json`'s `defaultLanguage`, which it already used for the frame's
`<html lang>`, and H5P's strings take the same one. `lang` decides only
for a package that names no language, or `und`; English stays the
default and the fallback.

The embed's `&lang=` is the same fallback, and its test now expects the
English quiz in English on a German page. The two-players example drops
`lang="de"`, which no longer changed anything for its English package.

Closes #55.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fixture builder checks what it built against `GENERATED_FIXTURES`,
the list the next run clears and the demo build ships, and refused
german.h5p and english.h5p, which were built but not listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The design-differences list in AGENTS.md and the setup skill's embed
snippet line now say the content's language comes first, and `lang`
decides for a package that names none.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@alekswebnet
alekswebnet merged commit 17974e1 into main Oct 20, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

H5P's own strings follow the content's language

1 participant