Conversation
An archive reported that lameta 3.0.x wrote "qaa-x-languagename" where IMDI needs a 3-letter ISO 639-3 code, and that every language a user invented got the same code, qaa. Now each such language gets the next free code from the qaa..qtz range that ISO 639-3 sets aside, and IMDI carries only the primary subtag: <Id>ISO639-3:qab</Id><Name>Tolo</Name>. Behaviour - The user types a name. A new dialog, Add an Unlisted Language, asks for the name and the code, pre-filled with the next free code, and validates both. It replaces a window.alert. - The user may instead type a free code, such as "qax". The row then reads "Add an unlisted language using qax" and the dialog asks for the name. - No field offers a code from the range with no name. Such a language is of no use to an archive. - Typing the code of a language the project already has finds that language, with the project's own name, and offers no duplicate row. - The language finder knows all three of the project's language fields, so a session or a person can find a language the project invented, by code or by name. Export - resolvePrivateUseCodes gives each colliding tag of a 3.0.x project its own code, sorted alphabetically, so no file has to be rewritten. - The map and its lookups are lowercase, because 3.0.x built the tag from the typed name. No Id or Name ever carries "-x-", and a language element with no tag no longer throws. - The metadata-language sites use the same map, so one file cannot say qab in Language/Id and qaa in a LanguageId attribute. Fixes found while testing this - The dropdown was clipped by an ancestor with overflow hidden, so on the Session and Person forms the user saw nothing at all. The menu now renders in a portal. The e2e helper clicks the row, because reading its text does not prove the user can reach it. - Dragging the pills lost a name the file carried, such as "pta : Guarani". - The highlight was a teal that no palette entry holds, and the code beside the name did not meet WCAG AA on either ground. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AGENTS.md records that this repo uses no card tracker, so preflight and the other review skills stop asking. CLAUDE.md imports it, because Claude Code reads CLAUDE.md and not AGENTS.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…session languages Devin found that locale/en/fields.po held a msgid with unescaped quotes. A PO string ends at the first unescaped quote, so the entry truncated and left stray tokens behind. The cause is extractFromJSON.ts, which interpolated a description into a PO string with no escaping, so it broke a second entry as well. Escape at the generator and regenerate. A new test reads the generated catalogs and refuses any malformed string. The two session-language sites in ImdiGenerator took the name from the language finder alone. For a tag that nothing knows, the finder returns the tag itself, which would write a raw tag into a Name element. Use nameForExport, as the actor path already does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
[Claude Opus 5 from Hatton's machine during preflight] Consulted Devin on 2026-08-27 up to commit Two rounds. Round 1 ran against
One Investigate flag stands, mirrored as a review thread above: Session-only invented languages fall outside the collision map. Confirmed real, and on the preflight decision report, because it reopens an allocation-scope decision that the plan settled. Three informational flags, assessed, no action:
|
An unlisted language may be created only in Subject Languages on the Project tab, which is the one field that carries canCreateNew. The gate already held, but nothing tested it, and losing it would bring back the defect this branch set out to fix: the allocator reads only the project's own language fields, so two sessions would each be given qaa, and both languages would export as ISO639-3:qaa. Two end-to-end tests type a name that matches no language into a session field and into a person field, and refuse a create row in the menu. Adding canCreateNew to the session field makes the first test fail, so the guard works. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
[Claude Opus 5 from Hatton's machine during preflight] Consulted Devin on 2026-08-27 up to commit Round three. No new actionable finding. Both earlier actionable items stay marked resolved by Devin: the unescaped quotes in the catalog, and the session Name that bypassed Devin repeats the Investigate flag Session-only invented languages fall outside the collision map. Its thread above now carries the answer and is resolved: a user cannot create an unlisted language outside the Project tab, so every invented language is in a project language field and therefore in the collision map. Commit One new informational flag, Names preserved for languages the file already carried. It notes that |
The test saved it to the repository root, which .gitignore does not cover, so every end-to-end run left an untracked PNG behind. playwright.config.ts already sets outputDir to tmp/playwright-output, and .gitignore covers tmp/. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Hi John, @hatton Semantically, the iso 639 identifier “und” is the appropriate identifier here not “qaa” or any other identifier in the reserved/“special use” block. The use of the ‘-x-‘ construct is a BCP-47 convention and not an iso 639 thing so |
Problem
An archive (ELAR) cannot ingest IMDI files that lameta 3.0.x writes. For a language that ISO 639-3 does not list, lameta wrote the whole tag into the IMDI language id, for example
<Id>ISO639-3:qaa-x-Kürbinian</Id>, where only a 3-letter code belongs. It also gave every such language the same code,qaa, so an archive could not tell two invented languages apart. lameta V2 let the user type a code and a name, and it exportedISO639-3:qab, which is what the archive expects.Cause
In V2 the Subject Language field had
type: "language", and the editor was a dialog with a Language Code box and a Name box. V3 changed the field totype: "languageChoices", and no field usestype: "language"any more, so that dialog became unreachable. The new type-ahead editor builtqaa-x-<name>unconditionally, and the two IMDI emitters for a session language and an actor language passed the tag through without reducing it to a code.What this PR changes
src/languageFinder/privateUseLanguages.ts, allocates the next unused code fromqaa..qtzfor each new language, and resolves a collision in an old project deterministically at export time. No project file is rewritten.qaa..qtzrange and against the codes the project already uses, and refuses a name that holds a semicolon or a colon. It replaces awindow.alertthat only announced what had already happened.canCreateNew. Two end-to-end tests hold that gate shut, because losing it would let two sessions each be givenqaa.qaxnow opens that dialog, instead of silently adding a nameless language. Typing a name that no language matches opens it too.qaorunlistedno longer produces an anonymousqaa.<Id>ISO639-3:qab</Id><Name>Tolo</Name>. Four metadata-language sites that bypassed the conversion now use it.document.body. Several ancestor panes haveoverflow: hidden, and on the short Session and Person fields they cut off the whole dropdown, so those fields appeared to have no type-ahead at all.qab-x-tolo:Tolointoqab-x-tolo.Devin review