Skip to content

accessibility: add Slovenian translations#90

Merged
Mc-Zen merged 15 commits into
Mc-Zen:mainfrom
hpcfzl:patch-1
Jul 10, 2026
Merged

accessibility: add Slovenian translations#90
Mc-Zen merged 15 commits into
Mc-Zen:mainfrom
hpcfzl:patch-1

Conversation

@hpcfzl

@hpcfzl hpcfzl commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Important

  • Added translations
  • Added plurality

Following language-contribution-guide.md.

The language code for this is sl.

Contains dual, cases, and genders.

Possible problems:

  • All three rules for translations of units all coincide I think, but for the first rule, the needs-plural function might require needs-dual as well
  • A float number should always imply the genitive case. However, until these translations support cases, there could be a notice somewhere that this is ignored. What action should be taken here?
  • The last digit determines the count, for example:
    • 101 meter (singular)
    • 102 metra (dual)
    • 103 metri (plural)
    • 104 metri (plural)
    • 105 metrov (plural, genitive)
    • 106 ... 200 metrov (plural, genitive)

I'm unsure about the:

  • Phrases dictionary:
    • Because plus and minus are the same as English, I thought they would be inherited as is done for prefixes and units. They're still there for now, but I would remove them and have phrases behave the same as prefixes and units in this regard
    • power:
      • I omitted potence from na stopnjo potence, but the difference is negligible. It's more similar to Russian. Also to consider would be potencirano na, which seems to align more to Finnish
  • Units dictionary:
    • Where becquerel, coulomb, gray, henry, hertz, joule, lux, ohm, siemens, sievert, watt, and weber can be inherited, I chose different words because readers might not pronounce them properly. The single exception is newton which is otherwise rarely njuten. Most deliberation was done for hertz and ohm
  • Power shorthands:
    • For example, $3 \frac{\mathrm{m}}{\mathrm{s}^2}$ would be better as tri metre na kvadratno sekundo rather than tri metre na sekundo na kvadrat, but for that, the gender would have to be considered as well. There's a Wikipedia page just for this composite unit and the corpus I checked also has an 8:4 concordance ratio in support for the former. Also $3 \mathrm{m}^2$ would preferably be trije kvadratni metri, not trije metri na kvadrat, although both are fine. So I'm not certain whether this change would be justifiable enough for the added complexity. It's simply that, as an adjective, it's less ambiguous
  • Tests

Numbers:

  • Does the translation work for both symmetric and asymmetric uncertainties? Does the translation for minus also work for the sign in front of the number?

    • Yes, I don't see why not, but I'm also not an expert for this

Power shorthands:

  • Many languages have dedicated shorthand expressions for certain powers like newton squared instead of newton to the power of two. If your language has such shorthands, you can define them in power-shorthands:

    • I mentioned this, but gender design would have to be considered. These would be changed as follows:
      • English for reference:
        • <unit> to the power of two/three<unit> squared/cubed → no more
      • Feminine units:
        • <enota> to the power of two<enota> na kvadratkvadratna <enota>
        • <enota> to the power of three<enota> na kubkubična <enota>
      • Masculine units:
        • <enota> to the power of two<enota> na kvadratkvadratni <enota>
        • <enota> to the power of three<enota> na kubkubični <enota>
      • Neuter units don't exist from what I can tell

Joining prefixes with units:

  • How are prefixes (like centi) joined to units?

    • Not special

I would also suggest these regarding language-contribution-guide.md:

  • accessibility.typ could link to the file
  • Could be my fault, but the times, power ... list there confused me initially

More uncertainties:

  • What's the order of language entries?
  • Are there formatting rules or is that manually done by you in review?
  • Should I have added tests?
  • I have trouble testing this myself, so I believe a snippet of all units and pluralities would be useful to others as well
  • Are we allowed to use more than .endswith() in pluralize?

See these changes in the PR.

hpcfzl added 3 commits July 3, 2026 17:58
* Linked `accessibility.typ`
* Indented the list
* Added phrases
* Added prefixes
* Added units
* Added power shorthands
* Added incomplete starter plurality
* Implemented the `pluralize` to add the possible pluralities
* See GitHub comment
@hpcfzl

hpcfzl commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Here's how I'm going about the pluralities so far:

Feminine:

  • 1: kandela, stopinja ...
  • 2: kandeli, stopinji ...
  • 3, 4: kandele, stopinje ...
  • 5+: kandel, stopinj ...

Masculine:

  • 1: amper, kelvin ...
  • 2: ampera, kelvina ...
    • ❯❯ dneva, henrija, litra, lumna, metra, vebra, tesli
  • 3, 4: amperi, kelvini ...
    • ❯❯ dnevi, henriji, litri, lumni, metri, vebri, tesle
  • 5+: amperov, kelvinov ...
    • ❯❯ dni, grejev, henrijev, hercev, litrov, lumnov, metrov, vebrov, tesel
About masculine

Here, tesla is indeed masculine, so tesla-tesli-teslov is also correct, but I think less common. Code-wise, treating tesla as feminine would be more compact, but no other units which would follow the same rule there.

Another example where more choices are possible is dan which can be dneva-dnevi-dnevov.

The masculine's ❯❯ are special rules for:

  • 2+: (1) dneva-dnevi-dnevi-dni
  • 2+: (1) tesli-tesle-tesle-tesel
  • 2+: (1) *men*mna-*mni-*mni-*mnov
  • 2+: (1) *i*ija-*iji-*iji-*ijev
  • 2+: (3) *ber, *ter*bra-*bri-*bri-*brob, *tra-*tri-*tri-*trov
  • 5+: (2) *c, , *j, , *ev

These special rules can be hardcoded for the (1), or more limited for the last entry specifically as only *c and *j are present.

More:

  • Compounds:
    ❯❯ astronomska enota, stopinja Celzija, kotna minuta, kotna sekunda
About more

These ❯❯ are all simple feminine and could follow the same rule as the feminine non-compounds. I used the str.split(" ") function for this.


A few more questions:

  • Is the hectare in this list because it's so common and not simply a prefix + unit? There's more such units on Wikipedia. Also the kilogram might not be needed now that there's this prefix + unit anyway, but I understand that it's an SI base unit.
  • I'm surprised Russian doesn't have a pluralize entry, I would think they have similar rules to ours. Is that why the forum post excludes Russian?
  • How to reliably be notified about new translation entries for my language? Should there be an issue to subscribe to?

So a TDLR of this commit could be that I:

  • Added a count argument to distinguish between the different pluralities

  • Allowed myself to somewhat hardcode translation of a few units since it's pretty much given they won't change, at most new will be added

  • The last digit determines the count ...

    This is now handled, and so is zero which I overlooked there, but

    A float number should always imply the genitive case.

    still needs to be resolved.

  • Haven't tested this at all

* Added floats into consideration
@hpcfzl

hpcfzl commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

A float number should always imply the genitive case. However, until these translations support cases, there could be a notice somewhere that this is ignored. What action should be taken here?

Since this is always the genitive singular, it's possible to implement into what I have added so far:

  •     fem.    mas.
    0   kandel  amperov
    1   kandela amper
    2   kandeli amperA
    3   kandelE amperi
    4   kandelE amperi
    5   kandel  amperov
    5.0 kandelE amperA  ←
    

    Notice how the 5.0's always-required genitive singular would be the same as:

    • plural-3-4 for feminine
    • dual for masculine

    There again is a special masculine unit teslaplural-3-4.

hpcfzl added 2 commits July 5, 2026 22:24
* Fixed link in TOC
* Changed link from German to English Wikipedia
* Added overlooked space to joined words
* Tested the code, see the GitHub comment
@hpcfzl

hpcfzl commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

In the code tests, via a snippet, I fixed these issues:

  • The symbols in conditional lists needed string conversion to match the compared unit:
    • For example, although degrees have a sym.degree key, the unit "°" passed to pluralize is not the same as sym.degree
  • A few compound words were incorrect for 0/5+ because I overlooked this:
    • 0/5+ astronomskIH enot
    • 0/5+ kotnIH minut
    • 0/5+ kotnIH sekund
  • Hours were within the masculine list because I overlooked this
Used test snippet

In multiplication of two same units, I noticed odd behaviour, but I also think such notation should be replaced by the user to use powers, so A AA^2. Otherwise for N m, V s ... I believe their alt always-singular can-be-plural is completely reasonable. Also, is there a requirement somewhere for space between units A A, and that the space-less units AA can't be parsed?

#set text(lang: "sl")
#set page(columns: 2)

#let unit-keys = units.sl.keys()
#let counts = (-5.5, -5, -4, -3, -2, -1.0, -1, 0, 1, 1.0, 2, 3, 4, 5, 5.5)

#let guad(unit, count) = repr(count) + " " + generate-unit-alt-description(
  ..parse-unit(unit).values(), value: count
) + "\n"

#context for unit in unit-keys {
  for count in counts {
    // Lone
    guad(unit, count)

    // Prefix
    guad("µ" + unit, count) // Must not be `sym.mu`

    // Multiplication can even be this way?
    guad(unit + " " + unit, count)

    // Division
    guad(unit + "/1", count)
    guad("1/" + unit, count)
    guad(unit + "/" + unit, count)
  }
  divider()
}

// Still untested:
// * `#generate-num-alt-description()`
// * `#parse-numeral()`

Units in the denominator are always singular.
From the third rule in language-contribution-guide.md.

About this, I have now also made a new revelation. The units in the denominator should always use the accusative singular. I overlooked this because masculine stays the same, apart from the special unit tesla. However, feminine is prone to change. See this for example:

Masculine:
1 kg   → 1 kilogram             (singular for reference)
1 1/kg → 1 na kilogram          (accusative singular)

Feminine:
1 au   → 1 astronomska enota    (singular for reference)
1 1/au → 1 na astronomskO enotO (accusative singular)

So the current quoted rule zero uses can't hold here. I suggest that a denominator bool is passed to pluralize.


More observations:

  • I noticed that 1/unit yields empty space + "per unit", is the empty space intentional?
  • The README uses metres, but the English alt is only meters, so should this be changed for consistency? I see that litres and metres were removed from zero.zi in v0.6.0, but could the text(lang: "en", region: "gb") be used to add them again?
  • I mentioned the N m and V s, which are correctly newton meter and volt sekunda, however it's more common to have newtonmeter and voltsekunda without the space. I don't think it's that necessary to implement this, but at the same time, I believe it's only applicable to these units, alongside A s and W s.

@Mc-Zen

Mc-Zen commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Hi @hpcfzl ,

Thank you for adding support for Slovenian!

I am surprised about the richness and degree of complexity that this language offers regarding plurals!

Let me go through your remarks and questions one by one.

Because plus and minus are the same as English, I thought they would be inherited as is done for prefixes and units. They're still there for now, but I would remove them and have phrases behave the same as prefixes and units in this regard

The inheritance is only used for the units and prefixes actually, to reduce the file size since many of those are common across languages.

For example, ... Would be better as tri metre na kvadratno sekundo rather than tri metre na sekundo na kvadrat, but for that, the gender would have to be considered as well. There's a Wikipedia page just for this composite unit and the corpus I checked also has an 8:4 concordance ratio in support for the former. Also ... would preferably be trije kvadratni metri, not trije metri na kvadrat, although both are fine. So I'm not certain whether this change would be justifiable enough for the added complexity. It's simply that, as an adjective, it's less ambiguous

Such case also exist for other languages that are already supported, however, I think it is out of scope to address this. After all, this feature is used to inform visually impaired people about the documents content and not to be grammatically flawless and idiomatic.

Power shorthands:

Regarding those, as I understand, there is no difficulty with the gender with the versions that you currently implemented (i.e. na kvadrat instead of kvadratna)? Also in English you can do both square meters or meters squared and I went for the latter.

I would also suggest these regarding language-contribution-guide.md:

👍 Thanks!

What's the order of language entries? Are there formatting rules or is that manually done by you in review?

Don't worry to much about this. I format with typstyle usually.

Should I have added tests?I have trouble testing this myself, so I believe a snippet of all units and pluralities would be useful to others as well

A few tests for notable cases like irregular plurals etc would be great. There is already an accessibility test file where the usage is already demonstrated.

Are we allowed to use more than .endswith() in pluralize?

Sure, that's up to the language.

@Mc-Zen

Mc-Zen commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Is the hectare in this list because it's so common and not simply a prefix + unit? There's more such units on Wikipedia. Also the kilogram might not be needed now that there's this prefix + unit anyway, but I understand that it's an SI base unit.

Exactly! The other ones are so rare that I don't think it's worth to add them.

I'm surprised Russian doesn't have a pluralize entry, I would think they have similar rules to ours. Is that why the forum post excludes Russian?

Russian is actually not supported yet. I just found the list of prefixes somewhere but then realized this was beyond my expertise... I hope someone will add Russian eventually.

How to reliably be notified about new translation entries for my language? Should there be an issue to subscribe to?

Good question. I could mention you on further PRs regarding Slovenian.

Added a count argument to distinguish between the different pluralities

Great!

@Mc-Zen

Mc-Zen commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Regarding tests: since your language is so much more complex with plural, it would be good to have some comprehensive tests for this.

@Mc-Zen

Mc-Zen commented Jul 6, 2026

Copy link
Copy Markdown
Owner

A float number should always imply the genitive case. However, until these translations support cases, there could be a notice somewhere that this is ignored. What action should be taken here?

First of all, be careful, the value is always a float, never an integer. If it is necessary to distinguish between 5 and 5.0, we could make a change to

value: float(info.int + "." + info.frac),

and convert to int if the fraction is "".

About this, I have now also made a new revelation. The units in the denominator should always use the accusative singular. I overlooked this because masculine stays the same, apart from the special unit tesla. However, feminine is prone to change. See this for example:

This is unfortunate because it makes everything much more complex. But passing a boolean flag for denominator would work.

The README uses metres, but the English alt is only meters, so should this be changed for consistency? I see that litres and metres were removed from zero.zi in v0.6.0, but could the text(lang: "en", region: "gb") be used to add them again?

Good catch I will update this myself. Actually the idea with being responsive to the region is good, I will consider this.

I mentioned the N m and V s, which are correctly newton meter and volt sekunda, however it's more common to have newtonmeter and voltsekunda without the space. I don't think it's that necessary to implement this, but at the same time, I believe it's only applicable to these units, alongside A s and W s.

Yes, this seems like a more specific convention that is out of scope for this project. There are similar examples with German and Finnish.

Comment thread src/accessibility.typ Outdated
Comment thread src/accessibility.typ Outdated
Comment thread src/accessibility.typ
Comment thread src/accessibility.typ Outdated
@Mc-Zen

Mc-Zen commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Thank you also for the corrections to the package read-me! Next time,I would prefer them to be in a separate PR but for now it's OK, just leave it in.

Also, it seems that at least part of the commits and messages were AI assisted (correct me if I'm wrong). Since the translation and pluralization of the units is quite complex, this seems okay but I would appreciate an overview of which parts this applies to. It is important for me to know what was human-reviewed, because of course I could also ask AI myself but I couldn't judge the quality of the output for most languages.

@hpcfzl

hpcfzl commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Also, it seems that at least part of the commits and messages were AI assisted (correct me if I'm wrong). Since the translation and pluralization of the units is quite complex, this seems okay but I would appreciate an overview of which parts this applies to. It is important for me to know what was human-reviewed, because of course I could also ask AI myself but I couldn't judge the quality of the output for most languages.

I can already disprove this.

I suspected you might think that, and I can't blame you, however I can assure you it's 0%-AI. I really did take all that time. In fact, I wouldn't trust AI for this as it's still not as reliable as the grammar sites intended for this. The same is true for code.

The confusion about the invalid syntax would be due to not testing anything until my last commit there.

Thanks for also taking the time to answer on your side, I'm going to treat your replies with the same amount of diligence.

@Mc-Zen

Mc-Zen commented Jul 6, 2026

Copy link
Copy Markdown
Owner

I can already disprove this.

I suspected you might think that, and I can't blame you, however I can assure you it's 0%-AI. I really did take all that time. In fact, I wouldn't trust AI for this as it's still not as reliable as the grammar sites intended for this. The same is true for code.

Thanks for clarifying! In this case I'm very sorry to even have assumed this and I want to thank you the more for your effort and for taking the time for your outstandingly detailed discussion of your thought and implementation process. This is very much appreciated!

@hpcfzl

hpcfzl commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Because plus and minus are the same as English, I thought they would be inherited as is done for prefixes and units. They're still there for now, but I would remove them and have phrases behave the same as prefixes and units in this regard

The inheritance is only used for the units and prefixes actually, to reduce the file size since many of those are common across languages.

Beside what you already answered, I see now that the phrases, unlike prefixes and units, contain a fallback key. So I assume the phrases inside fallback would have been the defaults here?

Power shorthands:

Regarding those, as I understand, there is no difficulty with the gender with the versions that you currently implemented (i.e. na kvadrat instead of kvadratna)? Also in English you can do both square meters or meters squared and I went for the latter.

Indeed, ¤ na kvadrat I believe is a pronoun and can be used the same everywhere. Whereas kvadrat* ¤ is an adjective based on the noun it's behind and is therefore different between genders.

Should I have added tests? I have trouble testing this myself, so I believe a snippet of all units and pluralities would be useful to others as well

A few tests for notable cases like irregular plurals etc would be great. There is already an accessibility test file where the usage is already demonstrated.

I added one in a later reply, but that covers all possibilities.

Are we allowed to use more than .endswith() in pluralize?

Sure, that's up to the language.

I also asked this to find where .endswith() is from, since I see no references to this in the code. Or is this just really hidden? That's why I ultimately used the default string's .ends-with().

@hpcfzl

hpcfzl commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Is the hectare in this list because it's so common and not simply a prefix + unit? There's more such units on Wikipedia. Also the kilogram might not be needed now that there's this prefix + unit anyway, but I understand that it's an SI base unit.

Exactly! The other ones are so rare that I don't think it's worth to add them.

I thought that the unit of are is common enough at least in Europe, otherwise I agree.

How to reliably be notified about new translation entries for my language? Should there be an issue to subscribe to?

Good question. I could mention you on further PRs regarding Slovenian.

I wouldn't mind that.

@hpcfzl

hpcfzl commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Regarding tests: since your language is so much more complex with plural, it would be good to have some comprehensive tests for this.

I did list the special plural rules in my initial reply, see About masculine.

So I suppose we could have a test for each -5.5, -5, -4, -3, -2, -1.0, -1, 0, 1, 1.0, 2, 3, 4, 5, 5.5 for each:

  • Regular plural rule
  • Special plural rule
  • Combined words on their own

@hpcfzl

hpcfzl commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

A float number should always imply the genitive case. However, until these translations support cases, there could be a notice somewhere that this is ignored. What action should be taken here?

First of all, be careful, the value is always a float, never an integer. If it is necessary to distinguish between 5 and 5.0, we could make a change to

value: float(info.int + "." + info.frac),

and convert to int if the fraction is "".

Yes, that needs to be distinguished, but unless I missed something, my test revealed that it's already correct without this change. See for example 1 mol versus 1.0 mola.

About this, I have now also made a new revelation. The units in the denominator should always use the accusative singular. I overlooked this because masculine stays the same, apart from the special unit tesla. However, feminine is prone to change. See this for example:

This is unfortunate because it makes everything much more complex. But passing a boolean flag for denominator would work.

Should I add this, or did you intend to? We use an unrelated denominator argument elsewhere, so I imagine we could use denom for the purpose of bool.

I mentioned the N m and V s, which are correctly newton meter and volt sekunda, however it's more common to have newtonmeter and voltsekunda without the space. I don't think it's that necessary to implement this, but at the same time, I believe it's only applicable to these units, alongside A s and W s.

Yes, this seems like a more specific convention that is out of scope for this project. There are similar examples with German and Finnish.

All right, this might be something to mention at the end of language-contribution-guide.md now that there's already three languages where this word joining would have been applicable.

hpcfzl added 2 commits July 6, 2026 22:30
* Applied review suggestions
* Corrected the comment about combined words being all-feminine
* Implemented accusative singular for the unit in a denominator
@hpcfzl

hpcfzl commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

About this, I have now also made a new revelation. The units in the denominator should always use the accusative singular. I overlooked this because masculine stays the same, apart from the special unit tesla. However, feminine is prone to change. See this for example:

This is unfortunate because it makes everything much more complex. But passing a boolean flag for denominator would work.

Should I add this, or did you intend to? We use an unrelated denominator argument elsewhere, so I imagine we could use denom for the purpose of bool.

Please excuse my patience. So I decided to add this denom bool. Slightly more invasive than I thought, but this was successful1. A question about this:

  • Is the only way to have units as $\frac{\mathrm{x}}{\mathrm{y} \mathrm{z}}$ to use x / y / z? The difference I'm thinking of in terms of alt is x per y z versus x per y per z? I tried x / (y z), but that doesn't parse. It's obviously much easier as-is because there's always only one denominator unit to consider, otherwise I think we would have to choose which unit in the denominator to really adapt, akin to how the numerator is treated.

Now I'm tempted to add the power shorthands kvadratna sekunda, as opposed to sekunda na kvadrat. But also not really because to determine kvadratna, the additional count and denom arguments now in pluralize would again be needed. Depends on how much you're opposed to this.

Please also review the count = 99 line for when count = auto, I forgot to mention that before. Would that be fine?


"2 N A / m s^2"     → 2 newton amper sekundi na kvadrat na meter
"2 N A / m / s^2"   → 2 newton ampera na meter na sekundo na kvadrat
"3 ha au^3 / h / T" → 3 hektar astronomske enote na kub na uro na teslo

Footnotes

  1. A few random tests:

* Removed unnecessary comment
@hpcfzl

hpcfzl commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Without the kvadratna sekunda change, here's the latest snippet to be used for the tests. I observe no error:

Latest test snippet
#let compare-sl = context {

  let nums = (-5.5, -5, -3, -2, -1.0, -1, 0, 1, 1.0, 2, 3, 5, 5.5, "1/")

  // Slovenian units, not all but the first which are unique
  // The entries are `unit: (0, 1, 1.0, 2, 3, 5, 5.5, denominator's)`
  // A `3` and `4` are always the same, and made inseparable in the code, so only `3` is tested for
  // Since the negatives are supposed to be a complete mirror of the positives, the first half of the array is taken from the second
  // Rules which only apply at higher counts are tested for lower as well anyway
  let units-sl = (
    // Feminine, regular
    cd: ("kandel", "kandela", "kandele", "kandeli", "kandele", "kandel", "kandele", "kandelo"),

    // Masculine, regular
    A: ("amperov", "amper", "ampera", "ampera", "amperi", "amperov", "ampera", "amper"),

    // Masculine, special hardcoded
    d: ("dni", "dan", "dneva", "dneva", "dnevi", "dni", "dneva", "dan"),
    H: ("henrijev", "henri", "henrija", "henrija", "henriji", "henrijev", "henrija", "henri"),
    lm: ("lumnov", "lumen", "lumna", "lumna", "lumni", "lumnov", "lumna", "lumen"),
    T: ("tesel", "tesla", "tesle", "tesli", "tesle", "tesel", "tesle", "teslo"),

    // Masculine, special rule for `*ber/*ter`
    L: ("litrov", "liter", "litra", "litra", "litri", "litrov", "litra", "liter"),

    // Masculine, special rule for `*c/*j`
    Gy: ("grejev", "grej", "greja", "greja", "greji", "grejev", "greja", "grej"),

    // Combined words
    au: ("astronomskih enot", "astronomska enota", "astronomske enote", "astronomski enoti", "astronomske enote", "astronomskih enot", "astronomske enote", "astronomsko enoto"),
    sym.degree + "C": ("stopinj Celzija", "stopinja Celzija", "stopinje Celzija", "stopinji Celzija", "stopinje Celzija", "stopinj Celzija", "stopinje Celzija", "stopinjo Celzija"),
  )

  for (key, words) in units-sl {
    words = words.slice(1, -1).rev() + words
    if nums.len() != words.len() {
      panic("The `nums` and `words` arrays for `" + key + "` need to be of same length")
    }

    let pairs = nums.zip(words)
    let (denom, denom-unit) = pairs.pop()

    let guad(u, n) = generate-unit-alt-description(
      ..parse-unit(u).values(), value: n,
    )

    // All integer and float numbers
    for (count, unit) in pairs {
      assert.eq(guad(key, count), unit)
    }
    // When the unit is in a denominator; a hardcoded count here should be sufficient
    assert.eq(guad(denom + key, 99), " na " + denom-unit)
  }

}

#compare-sl

Only a single unit is tested at once, because more units in the numerator behave the same as English in that they're always-singular always-singular ... always-plural.

As I had mentioned previously, the " na " fails without the first space because I added no unit to the numerator. Not sure how intentional this is.

To be complete, this snippet would also need:

  • generate-num-alt-description()
  • parse-numeral()

Although I don't fully understand what these would test.

Otherwise, feel free to add the tests and merge when ready!

@Mc-Zen

Mc-Zen commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Beside what you already answered, I see now that the phrases, unlike prefixes and units, contain a fallback key. So I assume the phrases inside fallback would have been the defaults here?

It's sort of a different kind of fallback that is engaged when the language is not supported at all (however, this symbolic notation only works for numbers; for units, everything is much more complex) instead of a default for individual keys.

Indeed, ¤ na kvadrat I believe is a pronoun and can be used the same everywhere. Whereas kvadrat* ¤ is an adjective based on the noun it's behind and is therefore different between genders.

Ok, then let us stick to the pronoun!

I also asked this to find where .endswith() is from, since I see no references to this in the code. Or is this just really hidden? That's why I ultimately used the default string's .ends-with().

Oh, this is a typo on my part! It should be ends-with all the time. Apparently there is no test case yet that covers this branch. I will fix that and add some cases in a future PR.

I thought that the unit of are is common enough at least in Europe, otherwise I agree.

That's actually correct, although still less used than hectare, I think. It never even received official status of an non-SI but SI-compliant unit (the hectare on the other hand did, but lost it recently).

Good question. I could mention you on further PRs regarding Slovenian.
I wouldn't mind that.

👍

I did list the special plural rules in my initial reply, see #90 (comment).
So I suppose we could have a test for each -5.5, -5, -4, -3, -2, -1.0, -1, 0, 1, 1.0, 2, 3, 4, 5, 5.5 for each:

Regular plural rule
 Special plural rule
 Combined words on their own

That sounds reasonable. It might not be necessary to test all the negative cases as the source code clearly shows that you just take the absolute of the number. One or two cases for negative numbers should suffice.

@Mc-Zen

Mc-Zen commented Jul 8, 2026

Copy link
Copy Markdown
Owner

A float number should always imply the genitive case. However, until these translations support cases, there could be a notice somewhere that this is ignored. What action should be taken here?

First of all, be careful, the value is always a float, never an integer. If it is necessary to distinguish between 5 and 5.0, we could make a change to

value: float(info.int + "." + info.frac),

and convert to int if the fraction is "".

Yes, that needs to be distinguished, but unless I missed something, my test revealed that it's already correct without this change. See for example 1 mol versus 1.0 mola.

I'm confused, the float constructor should always return a float and never. Where can I see your example? I think you didn't push any test files yet.

I mentioned the N m and V s, which are correctly newton meter and volt sekunda, however it's more common to have newtonmeter and voltsekunda without the space. I don't think it's that necessary to implement this, but at the same time, I believe it's only applicable to these units, alongside A s and W s.

Yes, this seems like a more specific convention that is out of scope for this project. There are similar examples with German and Finnish.

All right, this might be something to mention at the end of language-contribution-guide.md now that there's already three languages where this word joining would have been applicable.

Sounds good!

About this, I have now also made a new revelation. The units in the denominator should always use the accusative singular. I overlooked this because masculine stays the same, apart from the special unit tesla. However, feminine is prone to change. See this for example:

This is unfortunate because it makes everything much more complex. But passing a boolean flag for denominator would work.

Should I add this, or did you intend to? We use an unrelated denominator argument elsewhere, so I imagine we could use denom for the purpose of bool.

Please excuse my patience. So I decided to add this denom bool. Slightly more invasive than I thought, but this was successful. A question about this:

* Is the only way to have units as [..] to use `x / y / z`? The difference I'm thinking of in terms of alt is `x per y z` versus `x per y per z`? I tried `x / (y z)`, but that doesn't parse. It's obviously much easier as-is because there's always only one denominator unit to consider, otherwise I think we would have to choose which unit in the denominator to really adapt, akin to how the numerator is treated.

We need to distinguish between specifying a unit and how it is displayed. For specifying a unit, no parentheses are supported and you need to repeat the slash. For displaying, zero supports three distinct modes (fractions, inline, powers). However for the alt description, the best unambiguous way is to repeat the per for each denominator unit, in my opinion.

Now I'm tempted to add the power shorthands kvadratna sekunda, as opposed to sekunda na kvadrat. But also not really because to determine kvadratna, the additional count and denom arguments now in pluralize would again be needed. Depends on how much you're opposed to this.

I see that this would give more idiomatic results. But the gain is not worth the complexity I feel, as long as any native speaker would still understand.

Comment thread src/accessibility.typ Outdated
Comment thread src/accessibility.typ Outdated
Comment thread src/accessibility.typ Outdated
Comment thread src/accessibility.typ
Comment thread src/accessibility.typ Outdated
@Mc-Zen

Mc-Zen commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Without the kvadratna sekunda change, here's the latest snippet to be used for the tests. I observe no error:
Latest test snippet

To be complete, this snippet would also need:

* `generate-num-alt-description()`

* `parse-numeral()`

Although I don't fully understand what these would test.

Otherwise, feel free to add the tests and merge when ready!

looks good! While you currently only test description generation for units, generate-num-alt-description would be necessary to test description generation for numbers. This is really the easy part, because it only relates to the phrases dictionary.

@hpcfzl

hpcfzl commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

I'm confused, the float constructor should always return a float and never [integer]. Where can I see your example? I think you didn't push any test files yet.

This can already be observed in the first test snippet I shared #90 (comment). Simply paste this alongside modules imported into zero's test file. To your reply, I also mentioned you can notice the correct behaviour in 1 mol versus 1.0 mola. I added another test snippet later as you saw, and the same should still be true about the float there. I'm going to push a new commit containing the complete test, where I will also reassure myself about this. But I agree that this seems odd.

We need to distinguish between specifying a unit and how it is displayed. For specifying a unit, no parentheses are supported and you need to repeat the slash. For displaying, zero supports three distinct modes (fractions, inline, powers). However for the alt description, the best unambiguous way is to repeat the per for each denominator unit, in my opinion.

So for alt, that best way is also the only way from what I understand? This way, the alt for what is interpreted as x / (y / z) is always x per y per z, not x per y z? I ask this because for the latter, I think Slovenian would require a similar rule to the one used for the numerator.

Now I'm tempted to add the power shorthands kvadratna sekunda, as opposed to sekunda na kvadrat. But also not really because to determine kvadratna, the additional count and denom arguments now in pluralize would again be needed. Depends on how much you're opposed to this.

I see that this would give more idiomatic results. But the gain is not worth the complexity I feel, as long as any native speaker would still understand.

Understandable, it's already doable but I agree it's not that necessary when all the added code is considered.

hpcfzl added 2 commits July 9, 2026 05:41
* Applied review suggestions
* Added near-complete tests
@hpcfzl

hpcfzl commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

I have now commited near-complete tests. What I wondered was:

  • I can remember one can choose the comma delimiter in zero, should that be reflected in the alt? Especially since the only Slovenian reader I tried correctly interpreted only the comma delimiter. An English 1,234.567 would be a Slovenian 1.234,567.
  • Why does neither μA nor uA yield mikroamper? The unit-component-description doesn't even parse those.
  • Is there a reason why the tests are in a double context?

I'm confused, the float constructor should always return a float and never [integer]. Where can I see your example? I think you didn't push any test files yet.

This can already be observed in the first test snippet I shared #90 (comment). Simply paste this alongside modules imported into zero's test file. To your reply, I also mentioned you can notice the correct behaviour in 1 mol versus 1.0 mola. I added another test snippet later as you saw, and the same should still be true about the float there. I'm going to push a new commit containing the complete test, where I will also reassure myself about this. But I agree that this seems odd.

To further explain this, the tests we have don't use those zero-made numbers, which as you insist are always float as they're implemented at the moment. And you're right, when I for example pass float(1) to pretend to be zero's always-float, the mistake arises:

#context generate-unit-alt-description(..parse-unit("K").values(), value: float(1))

This would be 1 kelvina, because it's treated as 1.0 kelvina, but 1 kelvin is correct.

So your initial suggestion in #90 (comment) to convert to integer when there's no decimal part would be great.

I would have added another test for this as well, or wrap the count: n of the current test into float(n), but I assumed we should use zero's function instead. Could you recommend which function to use?

@Mc-Zen

Mc-Zen commented Jul 9, 2026

Copy link
Copy Markdown
Owner

So for alt, that best way is also the only way from what I understand? This way, the alt for what is interpreted as x / (y / z) is always x per y per z, not x per y z? I ask this because for the latter, I think Slovenian would require a similar rule to the one used for the numerator.

Yes it's the only way.

Well x/(y/z) would really be xz/y, not x per yz. I'm not quite sure where you are getting there. Zero only ever allows x/y/z as input which mathematically means x/(yz). Fo the alt description, the word per (or its translation) takes the place of the slash: all units prepended with "per" are in the denominator, all the rest is in numerator. So, for example A·s/(V·m) would be "ampere second per volt per meter". This should be least ambiguous and I don't think parentheses () can be expected to be correctly read with screen readers.

I can remember one can choose the comma delimiter in zero, should that be reflected in the alt? Especially since the only Slovenian reader I tried correctly interpreted only the comma delimiter. An English 1,234.567 would be a Slovenian 1.234,567.

Good point, the description generation uses the current setting for num.decimal-separator which is also used for document output. I figured this would be the easiest way and I would expect users to change this setting according to their language anyway. If we don't trust that, we can also add a key decimal-separator to phrases.

@Mc-Zen

Mc-Zen commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Is there a reason why the tests are in a double context?

Not any more (there used to be one), it's just important to have a context after setting the language.

Why does neither μA nor uA yield mikroamper? The unit-component-description doesn't even parse those.

Mmh, generate-unit-alt-description(..parse-unit("µA").values()) seems to work correctly.

I would have added another test for this as well, or wrap the count: n of the current test into float(n), but I assumed we should use zero's function instead. Could you recommend which function to use?

This is indeed harder to test. All these rather manual tests for the accessibility part are necessary because it is not possible to query the alt description of an equation (to my knowledge).

@Mc-Zen

Mc-Zen commented Jul 9, 2026

Copy link
Copy Markdown
Owner

So your initial suggestion in #90 (comment) to convert to integer when there's no decimal part would be great.

I implemented this!

@hpcfzl

hpcfzl commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

So for alt, that best way is also the only way from what I understand? This way, the alt for what is interpreted as x / (y / z) is always x per y per z, not x per y z? I ask this because for the latter, I think Slovenian would require a similar rule to the one used for the numerator.

Yes it's the only way.

Well x/(y/z) would really be xz/y, not x per yz. I'm not quite sure where you are getting there. Zero only ever allows x/y/z as input which mathematically means x/(yz). Fo the alt description, the word per (or its translation) takes the place of the slash: all units prepended with "per" are in the denominator, all the rest is in numerator. So, for example A·s/(V·m) would be "ampere second per volt per meter". This should be least ambiguous and I don't think parentheses () can be expected to be correctly read with screen readers.

This makes sense.

I'm not quite sure where you are getting there.

You're right, I rephrased the sentence, but forgot to change that as well.


I can remember one can choose the comma delimiter in zero, should that be reflected in the alt? Especially since the only Slovenian reader I tried correctly interpreted only the comma delimiter. An English 1,234.567 would be a Slovenian 1.234,567.

Good point, the description generation uses the current setting for num.decimal-separator which is also used for document output. I figured this would be the easiest way and I would expect users to change this setting according to their language anyway. If we don't trust that, we can also add a key decimal-separator to phrases.

I'm going to change both of 1.34 in the tests to use a comma, but without the addition of #set-num(decimal-separator: ","), so these tests are going to fail until we decide how to proceed here. See below.

I would expect users to change this setting according to their language anyway.

Same here. Still, there's bound to be users who won't.

If we don't trust that, we can also add a key decimal-separator to phrases.

Yes, I think this would definitely benefit the alt. I don't see how automatic per-language decimal separator would be unwanted. Again, this would be for the alts only.

@hpcfzl

hpcfzl commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

I would have added another test for this as well, or wrap the count: n of the current test into float(n), but I assumed we should use zero's function instead. Could you recommend which function to use?

This is indeed harder to test. All these rather manual tests for the accessibility part are necessary because it is not possible to query the alt description of an equation (to my knowledge).

Thanks for the float to integer fix regarding this. The behaviour should be correct in actual package use now. I will assume this won't change, and as it's so far not possible to easily test, I added no new test for this.


I see you also properly commented on the is-in-denom, thanks.

hpcfzl and others added 2 commits July 10, 2026 05:27
* Changed the tests' decimal separator to a decimal comma
* Changed the `mA` test to test for `µA`
@Mc-Zen

Mc-Zen commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Yes, I think this would definitely benefit the alt. I don't see how automatic per-language decimal separator would be unwanted. Again, this would be for the alts only.

I added translations for the decimal separator now!

Thanks for the float to integer fix regarding this. The behaviour should be correct in actual package use now. I will assume this won't change, and as it's so far not possible to easily test, I added no new test for this.

that's fine I might add tests later 👍

@Mc-Zen

Mc-Zen commented Jul 10, 2026

Copy link
Copy Markdown
Owner

I'm pretty happy now. If there is nothing more from your side, I am ready to merge this. I'll think about splitting out translations into separate files in the future.

@hpcfzl

hpcfzl commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Great, the decimal separator change seems to help the readers for other languages too, at least those quickly found online.

I see that you already corrected my overlooked Slovenian 0.5 to 0,5 in its test.

Because I don't have the software necessary to screen-read a PDF/UA, and I'm not inclined to perform software setups for them, I only ever confirmed the alt strings, not their actual use as alts in a PDF. But despite this, I'm almost certain that the translation matches to that of PDF readers' interpretation. I have notified https://a11y.si about this, and will provide an update on the verdict.

As for HTML, I believe alts should appear as MathML support progresses?

Ready to merge!

@hpcfzl hpcfzl marked this pull request as ready for review July 10, 2026 12:30
@Mc-Zen

Mc-Zen commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Because I don't have the software necessary to screen-read a PDF/UA, and I'm not inclined to perform software setups for them, I only ever confirmed the alt strings, not their actual use as alts in a PDF. But despite this, I'm almost certain that the translation matches to that of PDF readers' interpretation. I have notified https://a11y.si about this, and will provide an update on the verdict.

I checked that the descriptions actually end up in the PDF and that they are read by the NVDA screen reader. Unfortunately it has no math support for Slovenian but if the descriptions work for English and German, they also should for other languages.

As for HTML, I believe alts should appear as MathML support progresses?

Yes, I hope so. Currently, not even the manual alt descriptions end up in the HTML but I guess this is just a matter of time.


Huge thanks for this PR and the great amount of work that you invested in the Slovenian translations in order to work out all the tiny details! 🎉

@Mc-Zen Mc-Zen merged commit 1195601 into Mc-Zen:main Jul 10, 2026
1 check 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.

2 participants