Add multilingual cron descriptions - #1
Merged
Merged
Conversation
The cron-utils JAR this library replaces described crons in 16 languages
via a Java ResourceBundle. That was lost in the port: describeCronTabExression()
still took a locale but ignored it, and every description was a hard-coded
English literal.
Descriptions are now built from message templates in i18n/<locale>.json,
one file per language, shipping the same 17 languages the JAR supported.
Unlike cron-utils, which translated ~26 short atoms and concatenated them in
a word order fixed by Java, each template here is a whole phrase, so a
language controls its own word order -- month_day is "{1} {2}" in English
and Japanese but "{2} de {1}" in Spanish.
Locale resolution mirrors ResourceBundle: pt-BR is served by en.json, then
pt.json, then pt_BR.json, so a partial translation degrades one string at a
time. Both pt-BR and pt_BR are accepted.
Month names, day names and ordinals are shipped as bundle data rather than
read from the engine. LSDateFormat() does not exist on every CFML engine
(BoxLang, which the test suite runs on, has no such function), and shipping
them keeps output identical everywhere while putting every visible string in
front of the translator.
Ordinal overrides are keyed on the exact day of the month and are the one
key never inherited from the base bundle. Ordinal rules do not transfer
between languages: English marks 1, 21 and 31 alike, French marks only the
1st, so inheriting would render "le 21er".
Also fixes two description bugs found while restructuring:
* a daily task at a time other than the hour, e.g. "0 30 9 * * *", fell
through to the raw-cron fallback instead of "every day at 09:30". The
fixed-time-of-day branch required a zero minute; the wildcard-hour branch
above it already claims every ambiguous case, so the check was redundant.
* a stepped hour field with no dedicated case, e.g. "0 0 */5 * * *", was
described as "every 5 minutes". The interval ladder is now driven by the
field being described rather than by guessing the unit from its bound.
TRANSLATIONS.md explains how to review a language or add one, and
docs/translations/<lang>.md gives a per-language sheet showing real output
for every kind of expression Chrono can describe. Both are generated from
the live library by `box task run TranslationDocs`, so they cannot drift
from what the code actually produces.
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.
The cron-utils JAR this library replaces described crons in 16 languages via a Java ResourceBundle. That was lost in the port: describeCronTabExression() still took a locale but ignored it, and every description was a hard-coded English literal.
Descriptions are now built from message templates in i18n/.json, one file per language, shipping the same 17 languages the JAR supported.
Unlike cron-utils, which translated ~26 short atoms and concatenated them in a word order fixed by Java, each template here is a whole phrase, so a language controls its own word order -- month_day is "{1} {2}" in English and Japanese but "{2} de {1}" in Spanish.
Locale resolution mirrors ResourceBundle: pt-BR is served by en.json, then pt.json, then pt_BR.json, so a partial translation degrades one string at a time. Both pt-BR and pt_BR are accepted.
Month names, day names and ordinals are shipped as bundle data rather than read from the engine. LSDateFormat() does not exist on every CFML engine (BoxLang, which the test suite runs on, has no such function), and shipping them keeps output identical everywhere while putting every visible string in front of the translator.
Ordinal overrides are keyed on the exact day of the month and are the one key never inherited from the base bundle. Ordinal rules do not transfer between languages: English marks 1, 21 and 31 alike, French marks only the 1st, so inheriting would render "le 21er".
Also fixes two description bugs found while restructuring:
TRANSLATIONS.md explains how to review a language or add one, and docs/translations/.md gives a per-language sheet showing real output for every kind of expression Chrono can describe. Both are generated from the live library by
box task run TranslationDocs, so they cannot drift from what the code actually produces.