Skip to content

feat(locale): one .voc per month, so a spelling can have its own line - #380

Draft
openvoiceos-bot wants to merge 1 commit into
devfrom
fix/t4767-per-month-voc
Draft

openvoiceos-bot wants to merge 1 commit into
devfrom
fix/t4767-per-month-voc

Conversation

@openvoiceos-bot

@openvoiceos-bot openvoiceos-bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

A .voc file is unordered. OVOS-INTENT-2 §4.3, verbatim:

.entity, .voc, and .blacklist share the slot-free format: a list of
templates using expansion (a|b) / [x] only, no named slots. They are
syntactically and semantically identical, and a loader parses all three the
same way — each loads as the union of the sample sets of all its lines
(OVOS-INTENT-1 §4).

A union has no order and no fixed length, so a month table cannot be a file
whose Nth line is the Nth month. Per-month granularity needs a file per month.

What the positional reading cost, measured on dev

Adding a third spelling of March on its own line — which §4.3 permits, because
the file is a union of its lines — on dev 6bda4d9:

DEV months loaded: 13
la 1 semaine de marz      -> month 4     (want 3)
la 1 semaine de avril     -> month 5     (want 4)
la 1 semaine de decembre  -> month None  (want 12)

December falls off the end. The same three spellings in month_march.voc on
this branch:

BRANCH months loaded: 12
la 1 semaine de marz      -> month 3   OK
la 1 semaine de mars      -> month 3   OK
la 1 semaine de avril     -> month 4   OK
la 1 semaine de decembre  -> month 12  OK

The design

month_1.voc through month_12.voc, one file per month, January first, every
spelling of that month on its own line. The number is in the file name,
never a line position, so a file's lines stay an unordered set and a spelling
may sit on any of them.

This is the shape chronologia already ships, and its own loader reads.
All 61 of its packaged locales carry month_1.voc … month_12.voc, and every
one of the 24 that also ships months.voc carries both. Using the same names
gives one shape for one thing across the two roots this loader searches,
instead of a second spelling that would need a translation layer or a migration
of a dependency. An earlier revision of this branch used month_<name>.voc and
would have created exactly that second shape.

The order lives in code. _MONTH_VOC lists the twelve file names in
calendar order, and the file NAME maps to the month number. No line number is
read.

_load_months has three cases, and the loud one is the middle:

locale state behaviour
all twelve present the twelve fragments, in _MONTH_VOC order
some present, some missing raises, naming the locale and each missing month file
none present reads the deprecated months.voc and warns

The fragment form is unchanged — _month_alt, deduped and longest-first inside
(?:…) — so test_locale_fr_month_vocab and
test_locale_kab_per_file_fallback, which assert on it, pass untouched.

months.voc is deprecated, and nothing in the fleet needs it now

Measured after the rename, across every locale reachable through both roots:

of 61 chronologia locales: 61 load twelve natively, 0 via the deprecated path, 0 broken

plus the 6 locales this repository ships, also natively. Nothing takes the
deprecated path, so no chronologia change is required.

months.voc support stays for a locale root outside the fleet that ships it
without the per-month files, and the warning names a computed removal version,
1.0.0, against the current 0.33.2a1.

An earlier revision of this branch argued that 18 locales would otherwise lose
their months. That was an artefact of the naming rather than a fact about the
dependency: those locales already had month_<n>.voc all along.

Consumer sweep before deprecating

gh search code "months.voc" over both orgs returns this repository and
ovos-localize, where the only code hit is a comment using the path as an
example (ovos_localize/locale_rules.py:41), with further hits in
classification datasets.

It does not return chronologia, which ships these files for 61 locales,
because code search indexes file content and not file names. A local clone
sweep found it.

Worth knowing for the next sweep of this kind, including the part it got wrong:
that sweep looked for months.voc and did not look for month_<n>.voc, which
is why the first revision of this branch invented a second name for a file the
dependency already had. A filename sweep has to enumerate the shapes it might
find, not only the one it is replacing.

Tests

test/test_month_per_file_voc.py, nine cases: every shipped locale has twelve
non-empty month files; two spellings of one month resolve to the same month
(fr février/fevrier, août/aout, décembre/decembre, de
märz/maerz); three spellings in one file all resolve, and again with the
three lines reversed, which a positional reader could not promise; a month deleted from THIS root is
filled from the fallback root, because both roots now share the names, so a
tree part-way through a migration is completed rather than left short; a
missing month raises with the locale and the month named when NO root carries
the locale, using an invented zz; and a control that a complete zz loads
twelve, so the raise is the missing file and not the invented locale.

A mutation control on the mapping: swapping January and February in
_MONTH_VOC fails both February spellings, so the name-to-month mapping is
pinned rather than assumed.

7 passed, 92 subtests passed. The month-related modules together:
38 passed, 1 skipped, 603 subtests passed.

The full local suite reached 93% with zero failures and was then stopped: the
box was at load average 27 and the process was starved at 0.0% CPU against
other work. That is a stopped run, not a pass. CI runs it here.

Withdrawn

The count guard cut earlier for this task is withdrawn and is not re-cut. It
argued from the premise that line N is month N, which the format does not grant.

T-4767.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

At your service! I've gathered all the check results for you. 🫡

I've aggregated the results of the automated checks for this PR below.

⚖️ License Check

Checking the paperwork! Everything seems in order. 📂

✅ No license violations found.

Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed.

🔨 Build Tests

Measuring the stability of the build output. 📏

✅ All versions pass

Python Build Install Tests pytest
3.10 ✅ ✅ ✅ 2900 passed, 3 skipped, 14 xfailed, 58366 warnings, 2462 subtests passed in 178.13s (0:02:58)
3.11 ✅ ✅ ✅ 2900 passed, 3 skipped, 14 xfailed, 58366 warnings, 2462 subtests passed in 92.38s (0:01:32)
3.12 ✅ ✅ ✅ 2900 passed, 3 skipped, 14 xfailed, 58366 warnings, 2462 subtests passed in 168.48s (0:02:48)

📊 Coverage

Coverage report incoming! Every line counts. 🎯

⚠️ 73.8% total coverage

Files below 80% coverage (32 files)
File Coverage Missing lines
ovos_date_parser/calendars.py 0.0% 2
ovos_date_parser/cycles.py 0.0% 2
ovos_date_parser/regnal.py 0.0% 2
ovos_date_parser/roman.py 0.0% 2
ovos_date_parser/dates_cs.py 53.3% 359
ovos_date_parser/dates_da.py 59.0% 246
ovos_date_parser/dates_uk.py 63.1% 343
ovos_date_parser/dates_nb.py 63.5% 179
ovos_date_parser/dates_nn.py 63.5% 179
ovos_date_parser/dates_ru.py 64.1% 299
ovos_date_parser/dates_it.py 64.5% 223
ovos_date_parser/dates_ca.py 64.8% 357
ovos_date_parser/dates_gl.py 66.1% 242
ovos_date_parser/dates_pl.py 66.3% 208
ovos_date_parser/dates_eu.py 66.6% 222
ovos_date_parser/dates_nl.py 66.7% 219
ovos_date_parser/dates_es.py 68.2% 229
ovos_date_parser/dates_ast.py 70.4% 219
ovos_date_parser/dates_en.py 71.0% 266
ovos_date_parser/dates_ro.py 71.5% 199
ovos_date_parser/dates_pt.py 71.7% 210
ovos_date_parser/dates_an.py 72.5% 172
ovos_date_parser/dates_bg.py 73.8% 106
ovos_date_parser/dates_hr.py 73.8% 107
ovos_date_parser/dates_fy.py 74.1% 158
ovos_date_parser/dates_sv.py 75.6% 144
ovos_date_parser/dates_oc.py 77.0% 161
ovos_date_parser/dates_el.py 77.2% 141
ovos_date_parser/dates_az.py 77.6% 127
ovos_date_parser/dates_sl.py 78.0% 86
ovos_date_parser/common.py 78.3% 20
ovos_date_parser/dates_de.py 78.4% 132

Full report: download the coverage-report artifact.


End of Line. ⬛

A .voc file is unordered. OVOS-INTENT-2 §4.3 defines the slot-free roles and
says each "loads as the union of the sample sets of all its lines". A union has
no order and no fixed length, so a month table cannot be a file whose Nth line
is the Nth month. Per-month granularity needs a file per month.

months.voc was read by position, and that reading made the format's own
allowance a defect. Adding a third spelling of March on its own line, which
§4.3 permits, on dev 6bda4d9:

    DEV months loaded: 13
    la 1 semaine de marz      -> month 4    (want 3)
    la 1 semaine de avril     -> month 5    (want 4)
    la 1 semaine de decembre  -> month None (want 12)

December falls off the end. The same three spellings in month_march.voc on this
branch answer 3, 3, 4 and 12.

month_1.voc through month_12.voc hold every spelling of one month each,
January first. The number is in the FILE NAME, never a line position, so a
file's lines stay an unordered set and a spelling may sit on any of them.

That is the shape chronologia already ships, and its own loader reads. All 61
of its packaged locales carry month_1.voc .. month_12.voc, and every one of
the 24 that also ships months.voc carries both. Using the same names gives one
shape for one thing across the two roots this loader searches, instead of a
second spelling that would need a translation layer or a migration of a
dependency.

THE ORDER LIVES IN CODE. _MONTH_VOC lists the twelve file names in calendar
order and the file NAME maps to the month number. No line number is read, so a
month's spellings are just lines, in any order.

_load_months has three cases and the loud one is the middle:

  all twelve present          the twelve fragments, in _MONTH_VOC order
  some present, some missing  raises, naming the locale and each missing file
  none present                reads the deprecated months.voc and warns

The fragment form is unchanged, so the two existing tests that assert on it
pass untouched.

months.voc is deprecated rather than deleted, but nothing in the fleet now
needs it: measured after the rename, all 61 chronologia locales load twelve
months natively and NONE takes the deprecated path. It stays for a locale root
outside the fleet that ships months.voc without the per-month files, and the
warning names a computed removal version, 1.0.0, against the current 0.33.2a1.

No chronologia change is required. An earlier revision of this branch used
month_<name>.voc and argued that 18 locales would otherwise lose their months;
that argument was an artefact of the naming, not a fact about the dependency.

Consumer sweep before deprecating: gh search code over both orgs returns this
repository and ovos-localize, where the only code hit is a comment using the
path as an example. It does NOT return chronologia, which ships these files for
61 locales, because code search indexes file content and not file names. A
local clone sweep found it. That sweep found the months.voc files; it did not
look for month_<n>.voc, which is why the first revision of this branch invented
a second name for a file the dependency already had.

Verified per locale: the 6 locales here and all 61 chronologia locales load
twelve from per-month files with no warning. Nothing takes the deprecated path
and nothing regresses.

The count guard cut earlier for this task is withdrawn and not re-cut. It
argued from the premise that line N is month N, which the format does not
grant.

T-4767.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@JarbasAl
JarbasAl force-pushed the fix/t4767-per-month-voc branch from 2812b65 to 3d60558 Compare September 28, 2026 21:26
@github-actions github-actions Bot added feature and removed feature labels Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants