NAME
Time::Keeper::Natural::Words - the words CLDR has none for, one small table a locale
VERSION
Version 0.02
SYNOPSIS
my $w = Time::Keeper::Natural::Words->for('en-GB'); # en's table, or undef
$w->starts('end of last month', 'end_of'); # 'end of'
$w->phrases('start_of'); # start of, the start of, ...
Time::Keeper::Natural::Words->locales; # the codes with a table
DESCRIPTION
CLDR has no words for "start of", "end of", "at", "on" or "the". Those come from a file a locale, words/<code>.txt beside the module, one key a line, the key, a tab, and the phrases separated by |.
A phrase stands before what it applies to ("end of", "fin de", "Ende"), followed by a space, or by nothing when it ends in an apostrophe ("fin d'", "dell'"); or it is a frame with {0} where the rest goes, as CLDR writes its own patterns, for a language that puts the word after or round it ("{0}末", "{0} 말", "{0} का अंत", "{0}ের শেষ"). In a locale whose words carry no spaces, neither does the match. A locale with no file of its own reads its parent's (en-GB reads en.txt), and one with none in its chain has no table: "coverage" in Time::Keeper::Natural says data for it. The keys, the whole list:
start_of the start of the period that follows
end_of the end of it
at joins a time to a day, or stands before a time
on stands before a day
skip words dropped where a part begins ("the")
and a chain joiner, where the locale's list pattern has none
of between "the third Friday" and its month
last "the last Friday of October"
range two points as an interval: "from {0} to {1}", "{0} until {1}"
A key alone means the language needs no word for it. A phrase is matched after the locale's CLDR words and may not be one: a table that takes one dies when it loads, naming the phrase and the word. A line # test: text => value is run by tools/wordcheck; a value of two moments with / between them is an interval, read by "parse_interval" in Time::Keeper::Natural. A range phrase holds {0} and then {1}, and none of its three parts may be a CLDR word.
METHODS
for
The table for a locale, from the nearest file in its chain, or undef. Read once a locale.
from_file
Time::Keeper::Natural::Words->from_file($file, 'en', 'en-GB');
A table read from a file, as for reads one: the file, the code it is for, and the code whose CLDR words it is checked against (the first by default).
frame
my ($rest, $phrase) = $w->frame('fin du mois dernier', 'end_of'); # ('mois dernier', 'fin du')
The text inside the first of a key's phrases that frames it, the longest phrase first, as typed, and the phrase as the file spells it; an empty list when none does. Case is ignored and a typographic apostrophe matches a plain one.
starts
The phrase of frame, or undef.
split_on
my ($left, $right, $phrase) = $w->split_on('le troisième vendredi du mois prochain', 'of');
The text either side of the first of a key's phrases standing between two parts, or an empty list.
articled
$w->articled('mois dernier'); # 'mois dernier', 'le mois dernier', 'la mois dernier', ...
The text, then the text after each skip phrase: an article a contraction swallowed ("fin du mois dernier" is "fin de le mois dernier") put back, for a locale whose CLDR words carry their article.
is
True when the text is exactly a phrase of the key.
phrases
The phrases of a key as the file spells them.
keys
The keys the file names, including the empty ones.
tests
The # test: lines, each a text and the value expected.
code
The code of the file read, en for a parser in en-GB.
file
Its path.
locales
The codes that have a file.
chain
Time::Keeper::Natural::Words->chain('zh-Hant-HK'); # zh-Hant-HK, zh-Hant, zh
The codes tried for a locale, its own first.
dir
Where the files are: beside the module once installed, or the distribution's share/words when the module runs from its own tree.
SEE ALSO
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)