Skip to content
This repository has been archived by the owner on Jul 17, 2020. It is now read-only.

Fix some minor issues in the English translations #293

Merged
4 commits merged into from
Jan 14, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,10 +456,15 @@ would be `["during", "rain", "next-wednesday"]`.
* `RAIN_TYPE`
* `SLEET_TYPE`
* `SNOW_TYPE`
* `["parenthetical", SNOW_TYPE, SNOW_ACCUMULATION]`: For daily or weekly
summaries, if a significant amount of snow is expected, we will qualify it
with the amount of expected snow accumulation on the ground. (For example,
"snow (3-4 in.) throughout the day".)
* `["parenthetical", EXPECTED_PRECIP_TYPE, SNOW_ACCUMULATION]`: For daily or
weekly summaries, if a significant amount of snow is expected, we will
qualify it with the amount of expected snow accumulation. (For example,
"snow (3-4 in.) throughout the day".) PLEASE NOTE that it is possible for a
chance of snow accumulation to be forecasted even if the expected
precipitation type is rain or sleet: this may occur if the forecasted
temperature is right around the freezing point. Translations should clarify
that the parenthetical refers to a chance of snow in such circumstances.
(For example, "sleet (chance of 3-4 in. of snow) throughout the day".)

In each of the below precipitation types, the intensity of precipitation is
(very approximately) as follows:
Expand Down
84 changes: 56 additions & 28 deletions lib/lang/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,48 @@ function join_with_shared_prefix(a, b, joiner) {

// HACK: This gets around "today through on Tuesday" or cases like it, which
// are incorrect in English.
if(m === "today" || m === "tomorrow")
if(m === "today" || m === "tomorrow") {
m = "on " + m;
}

while(i !== m.length &&
i !== b.length &&
m.charCodeAt(i) === b.charCodeAt(i))
// Skip the prefix of b that is shared with a.
while(
i !== m.length &&
i !== b.length &&
m.charCodeAt(i) === b.charCodeAt(i)
) {
++i;
}

while(i && m.charCodeAt(i - 1) !== 32)
// ...except whitespace! We need that whitespace!
while(i && b.charCodeAt(i - 1) !== 32) {
--i;
}

return a + joiner + b.slice(i);
}

function strip_prefix(period) {
return period.slice(0, 9) === "overnight" ? period.slice(4) :
period.slice(0, 7) === "in the " ? period.slice(7) :
return period.startsWith("overnight")? period.slice(4):
period.startsWith("in the ")? period.slice(7):
period;
}

function capitalize(str) {
// Do not capitalize articles, very short words, or units.
if(
str === "a" ||
str === "and" ||
str === "cm" ||
str === "in" ||
str === "of" ||
str === "with"
) {
return str;
}
return str[0].toUpperCase() + str.slice(1);
}

module.exports = {
"clear": "clear",
"no-precipitation": "no precipitation",
Expand Down Expand Up @@ -104,19 +126,29 @@ module.exports = {
"centimeters": "$1 cm.",
"less-than": "< $1",
"and": function(a, b) {
return join_with_shared_prefix(
a,
b,
a.indexOf(",") !== -1 ? ", and " : " and "
);
return join_with_shared_prefix(a, b, a.includes(",")? ", and ": " and ");
},
"through": function(a, b) {
return join_with_shared_prefix(a, b, " through ");
},
"with": "$1, with $2",
"range": "$1\u2013$2",
"parenthetical": function(a, b) {
return a + " (" + b + (a === "mixed precipitation" ? " of snow)" : ")");
// In the case of mixed precipitation, we want to clarify that the
// snow accumulation in the parenthetical is snow. In the case that it's
// of an unknown type or rain or sleet, we want to clarify that while snow
// isn't expected, it has a chance of occurring. The below checks do this.

// HACK: These are not the best ways to determine the precipitation type...
const is_mixed = a.startsWith("mixed");
const is_snow = a.endsWith("flurries") || a.endsWith("snow");
if(!is_mixed && !is_snow) {
b = "with a chance of " + b;
}
if(!is_snow) {
b = b + " of snow";
}
return a + " (" + b + ")";
},
"for-hour": "$1 for the hour",
"starting-in": "$1 starting in $2",
Expand All @@ -141,29 +173,25 @@ module.exports = {
"temperatures-rising": "high temperatures rising to $1 $2",
"temperatures-valleying": "high temperatures bottoming out at $1 $2",
"temperatures-falling": "high temperatures falling to $1 $2",
// Capitalize the first letter of every word, except if that word is
// "and". (This is a very crude bastardization of proper English titling
// rules, but it is adequate for the purposes of this module.)
// Capitalize the first letter of every word except "and", "or", and units.
// (This is a very crude bastardization of proper English titling rules, but
// it is adequate for the purposes of this module.)
"title": function(str) {
return str.replace(
/\b(?:a(?!nd\b)|c(?!m\.)|i(?!n\.)|[^\Waci])/g,
function(letter) {
return letter.toUpperCase();
}
);
return str.replace(/\w+/g, capitalize);
},
/* Capitalize the first word of the sentence and end with a period. */
// Capitalize the first word of the sentence and end with a period.
"sentence": function(str) {
/* Capitalize. */
str = str.charAt(0).toUpperCase() + str.slice(1);
// Capitalize.
str = capitalize(str);

/* Add a period if there isn't already one. */
if(str.charAt(str.length - 1) !== ".")
// Add a period if there isn't already one.
if(!str.endsWith(".")) {
str += ".";
}

return str;
},
"next-hour-forecast-status": "Next hour forecasts are $1 due to $2.",
"next-hour-forecast-status": "next hour forecasts are $1 due to $2",
"unavailable": "unavailable",
"temporarily-unavailable": "temporarily unavailable",
"partially-unavailable": "partially unavailable",
Expand Down
11 changes: 8 additions & 3 deletions test_cases/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@
"Heavy Snow (3\u20135 cm.)":
["title", ["parenthetical", "heavy-snow", ["centimeters", ["range", 3, 5]]]],

"Rain (with a Chance of 2\u20134 in. of Snow)":
["title", ["parenthetical", "medium-rain", ["inches", ["range", 2, 4]]]],

"Possible Thunderstorms":
["title", "possible-thunderstorm"],

Expand All @@ -260,9 +263,11 @@
["starting-in", "very-light-rain", ["less-than", ["minutes", 1]]]],

"Next hour forecasts are temporarily unavailable due to all nearby radar stations being offline.":
["sentence",["next-hour-forecast-status", "temporarily-unavailable", "station-offline"]],
["sentence", ["next-hour-forecast-status", "temporarily-unavailable", "station-offline"]],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should make the linter yell about these since otherwise i'll keep doing it 😞

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The linter doesn't check JSON :(

midori:translations jay$ ./node_modules/.bin/eslint test_cases/en.json 

/Users/jay/Projects/Dark Sky/translations/test_cases/en.json
  2:10  error  Parsing error: Unexpected token :

✖ 1 problem (1 error, 0 warnings)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭


"Next hour forecasts are partially unavailable due to gaps in coverage from nearby radar stations.":
["sentence",["next-hour-forecast-status", "partially-unavailable", "station-incomplete"]],
["sentence", ["next-hour-forecast-status", "partially-unavailable", "station-incomplete"]],

"Next hour forecasts are unavailable due to all nearby radar stations being offline.":
["sentence",["next-hour-forecast-status", "unavailable", "station-offline"]]
["sentence", ["next-hour-forecast-status", "unavailable", "station-offline"]]
}