Upgrade to LibLouis 3.39.0 and carry the full table metadata - #26
Merged
Merged
Conversation
Rebuilt liblouis.dll from the 3.39.0 tag for Windows x64 with UCS-4 (UTF-32) widechars, and refreshed the bundled tables: 478 files, up from 472. New tables: en-nz-g1.utb and en-nz-g2.ctb (English as used in New Zealand, following Braille Authority of New Zealand Aotearoa Trust policy), ht-g1.utb with ht-frenchcompatibility.uti (Haitian Creole), ru-math.uti (Russian mathematical braille), and fr-bfu-comp6-puncs-math.uti. None removed. The two Dutch tables generated from m4 templates, nl-chardefs.uti and nl-NL-g0.utb, are carried over from 3.38.0: their .in templates are unchanged since that tag and the rule that expands them is a bare "m4 -G" with no defines, so the output is identical. The three nmake patches this build needed in 3.38.0 are down to one. The missing stdbool.h include and the strncasecmp shim were both fixed upstream in 3.39.0, which also gained a Windows NMAKE CI job. Still patched locally: windows/include/config.h defines PACKAGE_VERSION as "liblouis-3.39.0", where autotools yields a bare "3.39.0", so an unpatched nmake build reports a version lou_version() callers cannot parse.
TranslationTable described a table with a single language and a single
type. LibLouis does not: the manual states that "the same key may appear
multiple times in a table", and in 3.39.0 twenty-two tables declare
several languages. he-IL.utb (Israeli braille) declares Hebrew, Arabic and
English but was discoverable only as Hebrew; ancient-languages-us.utb
declares thirty-six. Eight tables declare both a computer and a literary
type, of which only the first survived.
Languages and TableTypes are therefore lists, replacing the scalar
Language and TableType. The metadata that was dropped altogether is now
carried too: IndexName, Region, Grade, System, Variant, Version, Locale
and UnicodeRange. Grade is a string because 1.2, 1.3, 1.4 and 1.5 are real
grades.
Two of those fields are RFC 4647 extended language ranges rather than
plain codes -- he-IL.utb declares "region: *-IL", IPA.utb declares
"language: *-fonipa" -- so LanguageRange implements the extended filtering
of RFC 4647 section 3.3.2, the rule LibLouis itself applies in
lou_findTable. FindByLanguage now matches that way instead of comparing
strings, so FindByLanguage("en-GB") finds the tables declaring plain "en",
and FindByLanguage("ar") finds Israeli braille.
TranslationTable becomes a sealed record rather than a readonly record
struct. The synthesized equality of a record compares list members by
reference, so keeping the struct would have quietly dropped the value
equality the type documents; Equals and GetHashCode are written out
instead and compare the lists element by element.
tables.json is regenerated with the updated LLJT, which also restores
ancient-languages-us.utb and ancient-languages-borger.utb: LLJT used to
match metadata lines by substring, so the word "language" in those tables'
display names shadowed their language fields and both were dropped from
the file entirely. 249 tables are now described, up from 244.
ListLanguages gains curated English names for the language codes .NET
cannot name -- jpa, oar, obm and xdm among the ones the multi-language
tables bring in -- and a test now fails if any bundled language would
surface to a UI as a bare code.
FindByLanguage("en-GB") returns every English table, which reads like a
bug and is not one: no LibLouis table narrows its language to en-GB. Every
English table declares plain "language: en" and puts the country in the
separate region field, so the RFC 4647 answer to "what can a British
reader use" really is all of them.
Selecting the specifically British tables means filtering by region, and
the language filter is still needed alongside it -- regions are extended
ranges too, so a bare FindByRegion("en-GB") also matches the two
Greek-for-English-speakers tables, whose region is the broader range "en".
Worth knowing before building a country picker: Unified English Braille
declares no region at all, being an international code rather than a
national one, so a region filter drops the very tables the U.K. has used
since 2011.
Adds a README section, a CHANGELOG note on the surprising case, and two
tests that pin both behaviors down.
Menelion
force-pushed
the
feature/liblouis-3.39
branch
from
September 2, 2026 18:08
1695b27 to
2c9717f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrades the bundled LibLouis to 3.39.0 and reworks translation table metadata to carry what LibLouis actually declares. Breaking API changes — this is a 3.0.0, not the 2.1.0 the upgrade alone would have been.
LibLouis 3.39.0
liblouis.dllrebuilt from the 3.39.0 tag for Windows x64 with UCS-4 (UTF-32) widechars, and all bundled tables refreshed: 478 files, up from 472. New:en-nz-g1.utbanden-nz-g2.ctb(English as used in New Zealand, following Braille Authority of New Zealand Aotearoa Trust policy),ht-g1.utbwithht-frenchcompatibility.uti(Haitian Creole),ru-math.uti(Russian mathematical braille),fr-bfu-comp6-puncs-math.uti. None removed. The release also brings an overhauled Portuguese grade 1 table, better back-translation for the Bulgarian, Italian and Biblical Hebrew tables, and 5000+ new English grade 3 hyphenation patterns.The two Dutch tables generated from m4 templates are carried over from 3.38.0: their
.intemplates are unchanged since that tag and the expansion rule is a barem4 -Gwith no defines, so the output is identical.Two of the three nmake patches this build needed in 3.38.0 are gone — the missing
stdbool.hinclude and thestrncasecmpshim were fixed upstream, which also gained a Windows NMAKE CI job. One remains, and it is an upstream bug worth reporting separately:windows/include/config.hdefinesPACKAGE_VERSIONas"liblouis-3.39.0"where autotools yields a bare"3.39.0", so an unpatched nmake build returns a version stringlou_version()callers cannot parse.Why the metadata rework
TranslationTabledescribed a table as having one language and one type. LibLouis does not work that way — the manual states plainly that "the same key may appear multiple times in a table":he-IL.utb(Israeli braille) declares Hebrew, Arabic and English, and was discoverable only as Hebrew.ancient-languages-us.utbdeclares thirty-six.computerandliterary; only the first survived.region,grade,system,variant,version,locale,unicode-rangeand#-index-namewere never read.tables.jsonentirely. The jsonifier matched metadata lines by substring, so the word "language" inside the display names ofancient-languages-us.utbandancient-languages-borger.utbshadowed their real language fields and both were filtered out as having no language. Fixed in Read the full table metadata, and every value of a repeated key liblouis-jsonify-tables#1, which this depends on.What changed
LanguagesandTableTypesare lists, replacing the scalarLanguageandTableType.IndexName,Region,Grade,System,Variant,Version,LocaleandUnicodeRangeare new.Gradeis a string because 1.2, 1.3, 1.4 and 1.5 are real grades.languageandregionare RFC 4647 extended language ranges, not plain codes —he-IL.utbdeclaresregion: *-IL,IPA.utbdeclareslanguage: *-fonipa. The newLanguageRangeclass implements the extended filtering of RFC 4647 §3.3.2, the rule LibLouis itself applies inlou_findTable, andFindByLanguagenow matches that way instead of comparing strings. SoFindByLanguage("en-GB")finds the tables declaring plainen, andFindByLanguage("ar")finds Israeli braille. Matching is asymmetric: a bareakkdoes not find a table declaring onlyakk-Latn.TranslationTablebecomes asealed recordrather than areadonly record struct. A record's synthesized equality compares list members by reference, so keeping the struct would have quietly dropped the value equality the type documents;EqualsandGetHashCodeare written out and compare the lists element by element.Also added:
TableCollection.FindByRegion(),FindComputer(),FindByGrade();TranslationTable.MatchesLanguage(),MatchesRegion(),IsOfType(),IsGrade().ListLanguages()gains curated English names for the codes .NET cannot name —jpa,oar,obm,xdmamong the ones the multi-language tables bring in — and a test now fails if any bundled language would reach a UI as a bare code.Migrating from 2.x
table.Language == "en"→table.MatchesLanguage("en")table.TableType→table.TableTypes, ortable.IsOfType(...)/IsLiteraryBraille()FindByFileName(...)returns a nullable reference now, sotable.Value.DisplayName→table.DisplayNameFileNameandDisplayNamearerequiredFull notes in CHANGELOG.md.
Verification
130 tests pass in Debug and Release, including new ones that compile and translate with every table added or at risk in this release, and a guard that
GetVersion()reports 3.39.x so a refreshed table set can never ship next to a stale DLL.dotnet packproduces a package carrying all 478 tables. A build withGITHUB_ACTIONS=true(warnings-as-errors, analyzers) is clean.Merge order
accessmind/liblouis-jsonify-tables#1 is merged, so this is unblocked. The committed
tables.jsonwas re-generated from LLJTmasterafter that merge and is byte-identical, so the two are in sync. Next step after this merges is taggingv3.0.0.